Whamcloud - gitweb
Land b_head_libcfs onto HEAD (20080805_1611)
[fs/lustre-release.git] / lustre / tests / multiop.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see [sun.com URL with a
20  * copy of GPLv2].
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 #ifndef _GNU_SOURCE
38 #define _GNU_SOURCE /* pull in O_DIRECTORY in bits/fcntl.h */
39 #endif
40 #include <stdio.h>
41 #include <fcntl.h>
42 #include <string.h>
43 #include <errno.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <sys/mman.h>
47 #include <signal.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50 #include <libcfs/libcfs.h>
51 #include <lustre/liblustreapi.h>
52
53 #define T1 "write data before unlink\n"
54 #define T2 "write data after unlink\n"
55 char msg[] = "yabba dabba doo, I'm coming for you, I live in a shoe, I don't know what to do.\n'Bigger, bigger,and bigger yet!' cried the Creator.  'You are not yet substantial enough for my boundless intents!'  And ever greater and greater the object became, until all was lost 'neath its momentus bulk.\n";
56 char *buf, *buf_align;
57 int bufsize = 0;
58 #define ALIGN 65535
59
60 char usage[] = 
61 "Usage: %s filename command-sequence\n"
62 "    command-sequence items:\n"
63 "        c  close\n"
64 "        C[num] create with optional stripes\n"
65 "        d  mkdir\n"
66 "        D  open(O_DIRECTORY)\n"
67 "        L  link\n"
68 "        l  symlink\n"
69 "        m  mknod\n"
70 "        M  rw mmap to EOF (must open and stat prior)\n"
71 "        N  rename\n"
72 "        o  open(O_RDONLY)\n"
73 "        O  open(O_CREAT|O_RDWR)\n"
74 "        r[num] read [optional length]\n"
75 "        R  reference entire mmap-ed region\n"
76 "        s  stat\n"
77 "        S  fstat\n"
78 "        t  fchmod\n"
79 "        T[num] ftruncate [optional position, default 0]\n"
80 "        u  unlink\n"
81 "        U  munmap\n"
82 "        w[num] write optional length\n"
83 "        W  write entire mmap-ed region\n"
84 "        y  fsync\n"
85 "        Y  fdatasync\n"
86 "        z[num] seek [optional position, default 0]\n"
87 "        _  wait for signal\n";
88
89 static int usr1_received;
90 void usr1_handler(int unused)
91 {
92         usr1_received = 1;
93 }
94
95 static const char *
96 pop_arg(int argc, char *argv[])
97 {
98         static int cur_arg = 3;
99
100         if (cur_arg >= argc)
101                 return NULL;
102
103         return argv[cur_arg++];
104 }
105
106 struct flag_mapping {
107        const char *string;
108        const int  flag;
109 } flag_table[] = {
110        {"O_RDONLY", O_RDONLY},
111        {"O_WRONLY", O_WRONLY},
112        {"O_RDWR", O_RDWR},
113        {"O_CREAT", O_CREAT},
114        {"O_EXCL", O_EXCL},
115        {"O_NOCTTY", O_NOCTTY},
116        {"O_TRUNC", O_TRUNC},
117        {"O_APPEND", O_APPEND},
118        {"O_NONBLOCK", O_NONBLOCK},
119        {"O_NDELAY", O_NDELAY},
120        {"O_SYNC", O_SYNC},
121 #ifdef O_DIRECT
122        {"O_DIRECT", O_DIRECT},
123 #endif
124        {"O_LARGEFILE", O_LARGEFILE},
125        {"O_DIRECTORY", O_DIRECTORY},
126        {"O_NOFOLLOW", O_NOFOLLOW},
127        {"", -1}
128 };
129
130 int get_flags(char *data, int *rflags)
131 {
132         char *cloned_flags;
133         char *tmp;
134         int flag_set = 0;
135         int flags = 0;
136         int size = 0;
137
138         cloned_flags = strdup(data);
139         if (cloned_flags == NULL) {
140                 fprintf(stderr, "Insufficient memory.\n");
141                 exit(-1);
142         }
143
144         for (tmp = strtok(cloned_flags, ":"); tmp;
145              tmp = strtok(NULL, ":")) {
146                 int i;
147
148                 size = tmp - cloned_flags;
149                 for (i = 0; flag_table[i].flag != -1; i++) {
150                         if (!strcmp(tmp, flag_table[i].string)){
151                                 flags |= flag_table[i].flag;
152                                 size += strlen(flag_table[i].string);
153                                 flag_set = 1;
154                                 break;
155                         }
156                 }
157         }
158         free(cloned_flags);
159
160         if (!flag_set) {
161                 *rflags = O_RDONLY;
162                 return 0;
163         }
164
165         *rflags = flags;
166         return size;
167 }
168
169 #define POP_ARG() (pop_arg(argc, argv))
170 #define min(a,b) ((a)>(b)?(b):(a))
171
172 int main(int argc, char **argv)
173 {
174         char *fname, *commands;
175         const char *newfile;
176         struct stat st;
177         size_t mmap_len = 0, i;
178         unsigned char *mmap_ptr = NULL, junk = 0;
179         int rc, len, fd = -1;
180         int flags;
181         int save_errno;
182         int verbose = 0;
183
184         if (argc < 3) {
185                 fprintf(stderr, usage, argv[0]);
186                 exit(1);
187         }
188
189         signal(SIGUSR1, usr1_handler);
190
191         fname = argv[1];
192
193         for (commands = argv[2]; *commands; commands++) {
194                 switch (*commands) {
195                 case '_':
196                         if (usr1_received == 0) {
197                                 if (verbose) {
198                                         printf("PAUSING\n");
199                                         fflush(stdout);
200                                 }
201                                 pause();
202                         }
203                         usr1_received = 0;
204                         signal(SIGUSR1, usr1_handler);
205                         break;
206                 case 'c':
207                         if (close(fd) == -1) {
208                                 save_errno = errno;
209                                 perror("close");
210                                 exit(save_errno);
211                         }
212                         fd = -1;
213                         break;
214                 case 'C':
215                         len = atoi(commands+1);
216                         fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
217                                              0, 0, len, 0);
218                         if (fd == -1) {
219                                 save_errno = errno;
220                                 perror("create stripe file");
221                                 exit(save_errno);
222                         }
223                         break;
224                 case 'd':
225                         if (mkdir(fname, 0755) == -1) {
226                                 save_errno = errno;
227                                 perror("mkdir(0755)");
228                                 exit(save_errno);
229                         }
230                         break;
231                 case 'D':
232                         fd = open(fname, O_DIRECTORY);
233                         if (fd == -1) {
234                                 save_errno = errno;
235                                 perror("open(O_DIRECTORY)");
236                                 exit(save_errno);
237                         }
238                         break;
239                 case 'l':
240                         newfile = POP_ARG();
241                         if (!newfile)
242                                 newfile = fname;
243                         if (symlink(fname, newfile)) {
244                                 save_errno = errno;
245                                 perror("symlink()");
246                                 exit(save_errno);
247                         }
248                         break;
249                 case 'L':
250                         newfile = POP_ARG();
251                         if (!newfile)
252                                 newfile = fname;
253                         if (link(fname, newfile)) {
254                                 save_errno = errno;
255                                 perror("symlink()");
256                                 exit(save_errno);
257                         }
258                         break;
259                 case 'm':
260                         if (mknod(fname, S_IFREG | 0644, 0) == -1) {
261                                 save_errno = errno;
262                                 perror("mknod(S_IFREG|0644, 0)");
263                                 exit(save_errno);
264                         }
265                         break;
266                 case 'M':
267                         mmap_len = st.st_size;
268                         mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
269                                         MAP_SHARED, fd, 0);
270                         if (mmap_ptr == MAP_FAILED) {
271                                 save_errno = errno;
272                                 perror("mmap");
273                                 exit(save_errno);
274                         }
275                         break;
276                 case 'N':
277                         newfile = POP_ARG();
278                         if (!newfile)
279                                 newfile = fname;
280                         if (rename (fname, newfile)) {
281                                 save_errno = errno;
282                                 perror("rename()");
283                                 exit(save_errno);
284                         }
285                         break;
286                 case 'O':
287                         fd = open(fname, O_CREAT|O_RDWR, 0644);
288                         if (fd == -1) {
289                                 save_errno = errno;
290                                 perror("open(O_RDWR|O_CREAT)");
291                                 exit(save_errno);
292                         }
293                         break;
294                 case 'o':
295                         len = get_flags(commands+1, &flags);
296                         commands += len;
297                         fd = open(fname, flags);
298                         if (fd == -1) {
299                                 save_errno = errno;
300                                 perror("open");
301                                 exit(save_errno);
302                         }
303                         break;
304                 case 'r':
305                         len = atoi(commands+1);
306                         if (len <= 0)
307                                 len = 1;
308                         if (bufsize < len) {
309                                 buf = realloc(buf, len + ALIGN);
310                                 if (buf == NULL) {
311                                         save_errno = errno;
312                                         perror("allocating buf for read\n");
313                                         exit(save_errno);
314                                 }
315                                 bufsize = len;
316                                 buf_align = (char *)((long)(buf + ALIGN) &
317                                                      ~ALIGN);
318                         }
319                         while (len > 0) {
320                                 rc = read(fd, buf_align, len);
321                                 if (rc == -1) {
322                                         save_errno = errno;
323                                         perror("read");
324                                         exit(save_errno);
325                                 }
326                                 if (rc < len)
327                                         fprintf(stderr, "short read: %u/%u\n",
328                                                 rc, len);
329                                 len -= rc;
330                         }
331                         break;
332                 case 'R':
333                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
334                                 junk += mmap_ptr[i];
335                         break;
336                 case 's':
337                         if (stat(fname, &st) == -1) {
338                                 save_errno = errno;
339                                 perror("stat");
340                                 exit(save_errno);
341                         }
342                         break;
343                 case 'S':
344                         if (fstat(fd, &st) == -1) {
345                                 save_errno = errno;
346                                 perror("fstat");
347                                 exit(save_errno);
348                         }
349                         break;
350                 case 't':
351                         if (fchmod(fd, 0) == -1) {
352                                 save_errno = errno;
353                                 perror("fchmod");
354                                 exit(save_errno);
355                         }
356                         break;
357                 case 'T':
358                         len = atoi(commands+1);
359                         if (ftruncate(fd, len) == -1) {
360                                 save_errno = errno;
361                                 printf("ftruncate (%d,%d)\n", fd, len);
362                                 perror("ftruncate");
363                                 exit(save_errno);
364                         }
365                         break;
366                 case 'u':
367                         if (unlink(fname) == -1) {
368                                 save_errno = errno;
369                                 perror("unlink");
370                                 exit(save_errno);
371                         }
372                         break;
373                 case 'U':
374                         if (munmap(mmap_ptr, mmap_len)) {
375                                 save_errno = errno;
376                                 perror("munmap");
377                                 exit(save_errno);
378                         }
379                         break;
380                 case 'v':
381                         verbose = 1;
382                         break;
383                 case 'w':
384                         len = atoi(commands+1);
385                         if (len <= 0)
386                                 len = 1;
387                         if (bufsize < len) {
388                                 buf = realloc(buf, len + ALIGN);
389                                 if (buf == NULL) {
390                                         save_errno = errno;
391                                         perror("allocating buf for write\n");
392                                         exit(save_errno);
393                                 }
394                                 bufsize = len;
395                                 buf_align = (char *)((long)(buf + ALIGN) &
396                                                      ~ALIGN);
397                                 strncpy(buf_align, msg, bufsize);
398                         }
399                         while (len > 0) {
400                                 rc = write(fd, buf_align, len);
401                                 if (rc == -1) {
402                                         save_errno = errno;
403                                         perror("write");
404                                         exit(save_errno);
405                                 }
406                                 if (rc < len)
407                                         fprintf(stderr, "short write: %u/%u\n",
408                                                 rc, len);
409                                 len -= rc;
410                         }
411                         break;
412                 case 'W':
413                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
414                                 mmap_ptr[i] += junk++;
415                         break;
416                 case 'y':
417                         if (fsync(fd) == -1) {
418                                 save_errno = errno;
419                                 perror("fsync");
420                                 exit(save_errno);
421                         }
422                         break;
423                 case 'Y':
424                         if (fdatasync(fd) == -1) {
425                                 save_errno = errno;
426                                 perror("fdatasync");
427                                 exit(save_errno);
428                         }
429                 case 'z':
430                         len = atoi(commands+1);
431                         if (lseek(fd, len, SEEK_SET) == -1) {
432                                 save_errno = errno;
433                                 perror("lseek");
434                                 exit(save_errno);
435                         }
436                         break;
437                 case '0':
438                 case '1':
439                 case '2':
440                 case '3':
441                 case '4':
442                 case '5':
443                 case '6':
444                 case '7':
445                 case '8':
446                 case '9':
447                         break;
448                 default:
449                         fprintf(stderr, "unknown command \"%c\"\n", *commands);
450                         fprintf(stderr, usage, argv[0]);
451                         exit(1);
452                 }
453         }
454
455         if (buf)
456                 free(buf);
457
458         return 0;
459 }