Whamcloud - gitweb
Branch b1_6
[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 #ifndef _GNU_SOURCE
5 #define _GNU_SOURCE /* pull in O_DIRECTORY in bits/fcntl.h */
6 #endif
7 #include <stdio.h>
8 #include <fcntl.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/mman.h>
14 #include <signal.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17
18 #define T1 "write data before unlink\n"
19 #define T2 "write data after unlink\n"
20 char buf[] = "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";
21
22 char usage[] = 
23 "Usage: %s filename command-sequence\n"
24 "    command-sequence items:\n"
25 "        c  close\n"
26 "        d  mkdir\n"
27 "        D  open(O_DIRECTORY)\n"
28 "        L  link\n"
29 "        l  symlink\n"
30 "        m  mknod\n"
31 "        M  rw mmap to EOF (must open and stat prior)\n"
32 "        N  rename\n"
33 "        o  open(O_RDONLY)\n"
34 "        O  open(O_CREAT|O_RDWR)\n"
35 "        r[num] read [optional length]\n"
36 "        R  reference entire mmap-ed region\n"
37 "        s  stat\n"
38 "        S  fstat\n"
39 "        t  fchmod\n"
40 "        T[num] ftruncate [optional position, default 0]\n"
41 "        u  unlink\n"
42 "        U  munmap\n"
43 "        w[num] write optional length\n"
44 "        W  write entire mmap-ed region\n"
45 "        y  fsync\n"
46 "        Y  fdatasync\n"
47 "        z[num] seek [optional position, default 0]\n"
48 "        _  wait for signal\n";
49
50 static int usr1_received;
51 void usr1_handler(int unused)
52 {
53         usr1_received = 1;
54 }
55
56 static const char *
57 pop_arg(int argc, char *argv[])
58 {
59         static int cur_arg = 3;
60
61         if (cur_arg >= argc)
62                 return NULL;
63
64         return argv[cur_arg++];
65 }
66
67 struct flag_mapping {
68        const char *string;
69        const int  flag;
70 } flag_table[] = {
71        {"O_RDONLY", O_RDONLY},
72        {"O_WRONLY", O_WRONLY},
73        {"O_RDWR", O_RDWR},
74        {"O_CREAT", O_CREAT},
75        {"O_EXCL", O_EXCL},
76        {"O_NOCTTY", O_NOCTTY},
77        {"O_TRUNC", O_TRUNC},
78        {"O_APPEND", O_APPEND},
79        {"O_NONBLOCK", O_NONBLOCK},
80        {"O_NDELAY", O_NDELAY},
81        {"O_SYNC", O_SYNC},
82 #ifdef O_DIRECT
83        {"O_DIRECT", O_DIRECT},
84 #endif
85        {"O_LARGEFILE", O_LARGEFILE},
86        {"O_DIRECTORY", O_DIRECTORY},
87        {"O_NOFOLLOW", O_NOFOLLOW},
88        {"", -1}
89 };
90
91 int get_flags(char *data, int *rflags)
92 {
93         char *cloned_flags;
94         char *tmp;
95         int flag_set = 0;
96         int flags = 0;
97         int size = 0;
98
99         cloned_flags = strdup(data);
100         if (cloned_flags == NULL) {
101                 fprintf(stderr, "Insufficient memory.\n");
102                 exit(-1);
103         }
104
105         for (tmp = strtok(cloned_flags, ":"); tmp;
106              tmp = strtok(NULL, ":")) {
107                 int i;
108
109                 size = tmp - cloned_flags;
110                 for (i = 0; flag_table[i].flag != -1; i++) {
111                         if (!strcmp(tmp, flag_table[i].string)){
112                                 flags |= flag_table[i].flag;
113                                 size += strlen(flag_table[i].string);
114                                 flag_set = 1;
115                                 break;
116                         }
117                 }
118         }
119         free(cloned_flags);
120
121         if (!flag_set) {
122                 *rflags = O_RDONLY;
123                 return 0;
124         }
125
126         *rflags = flags;
127         return size;
128 }
129
130 #define POP_ARG() (pop_arg(argc, argv))
131 #define min(a,b) ((a)>(b)?(b):(a))
132
133 int main(int argc, char **argv)
134 {
135         char *fname, *commands;
136         const char *newfile;
137         struct stat st;
138         size_t mmap_len = 0, i;
139         unsigned char *mmap_ptr = NULL, junk = 0;
140         int rc, len, fd = -1;
141         int flags;
142         int save_errno;
143
144         if (argc < 3) {
145                 fprintf(stderr, usage, argv[0]);
146                 exit(1);
147         }
148
149         signal(SIGUSR1, usr1_handler);
150
151         fname = argv[1];
152
153         for (commands = argv[2]; *commands; commands++) {
154                 switch (*commands) {
155                 case '_':
156                         if (usr1_received == 0)
157                                 pause();
158                         usr1_received = 0;
159                         signal(SIGUSR1, usr1_handler);
160                         break;
161                 case 'c':
162                         if (close(fd) == -1) {
163                                 save_errno = errno;
164                                 perror("close");
165                                 exit(save_errno);
166                         }
167                         fd = -1;
168                         break;
169                 case 'd':
170                         if (mkdir(fname, 0755) == -1) {
171                                 save_errno = errno;
172                                 perror("mkdir(0755)");
173                                 exit(save_errno);
174                         }
175                         break;
176                 case 'D':
177                         fd = open(fname, O_DIRECTORY);
178                         if (fd == -1) {
179                                 save_errno = errno;
180                                 perror("open(O_DIRECTORY)");
181                                 exit(save_errno);
182                         }
183                         break;
184                 case 'l':
185                         newfile = POP_ARG();
186                         if (!newfile)
187                                 newfile = fname;
188                         if (symlink(fname, newfile)) {
189                                 save_errno = errno;
190                                 perror("symlink()");
191                                 exit(save_errno);
192                         }
193                         break;
194                 case 'L':
195                         newfile = POP_ARG();
196                         if (!newfile)
197                                 newfile = fname;
198                         if (link(fname, newfile)) {
199                                 save_errno = errno;
200                                 perror("symlink()");
201                                 exit(save_errno);
202                         }
203                         break;
204                 case 'm':
205                         if (mknod(fname, S_IFREG | 0644, 0) == -1) {
206                                 save_errno = errno;
207                                 perror("mknod(S_IFREG|0644, 0)");
208                                 exit(save_errno);
209                         }
210                         break;
211                 case 'M':
212                         mmap_len = st.st_size;
213                         mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
214                                         MAP_SHARED, fd, 0);
215                         if (mmap_ptr == MAP_FAILED) {
216                                 save_errno = errno;
217                                 perror("mmap");
218                                 exit(save_errno);
219                         }
220                         break;
221                 case 'N':
222                         newfile = POP_ARG();
223                         if (!newfile)
224                                 newfile = fname;
225                         if (rename (fname, newfile)) {
226                                 save_errno = errno;
227                                 perror("rename()");
228                                 exit(save_errno);
229                         }
230                         break;
231                 case 'O':
232                         fd = open(fname, O_CREAT|O_RDWR, 0644);
233                         if (fd == -1) {
234                                 save_errno = errno;
235                                 perror("open(O_RDWR|O_CREAT)");
236                                 exit(save_errno);
237                         }
238                         break;
239                 case 'o':
240                         len = get_flags(commands+1, &flags);
241                         commands += len;
242                         fd = open(fname, flags);
243                         if (fd == -1) {
244                                 save_errno = errno;
245                                 perror("open");
246                                 exit(save_errno);
247                         }
248                         break;
249                 case 'r':
250                         len = atoi(commands+1);
251                         if (len <= 0)
252                                 len = 1;
253                         while(len > 0) {
254                                 if (read(fd, &buf,
255                                          min(len,sizeof(buf))) == -1) {
256                                         save_errno = errno;
257                                         perror("read");
258                                         exit(save_errno);
259                                 }
260                                 len -= sizeof(buf);
261                         }
262                         break;
263                 case 'S':
264                         if (fstat(fd, &st) == -1) {
265                                 save_errno = errno;
266                                 perror("fstat");
267                                 exit(save_errno);
268                         }
269                         break;
270                 case 'R':
271                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
272                                 junk += mmap_ptr[i];
273                         break;
274                 case 's':
275                         if (stat(fname, &st) == -1) {
276                                 save_errno = errno;
277                                 perror("stat");
278                                 exit(save_errno);
279                         }
280                         break;
281                 case 't':
282                         if (fchmod(fd, 0) == -1) {
283                                 save_errno = errno;
284                                 perror("fchmod");
285                                 exit(save_errno);
286                         }
287                         break;
288                 case 'T':
289                         len = atoi(commands+1);
290                         if (ftruncate(fd, len) == -1) {
291                                 save_errno = errno;
292                                 printf("ftruncate (%d,%d)\n", fd, len);
293                                 perror("ftruncate");
294                                 exit(save_errno);
295                         }
296                         break;
297                 case 'u':
298                         if (unlink(fname) == -1) {
299                                 save_errno = errno;
300                                 perror("unlink");
301                                 exit(save_errno);
302                         }
303                         break;
304                 case 'U':
305                         if (munmap(mmap_ptr, mmap_len)) {
306                                 save_errno = errno;
307                                 perror("munmap");
308                                 exit(save_errno);
309                         }
310                         break;
311                 case 'w':
312                         len = atoi(commands+1);
313                         if (len <= 0)
314                                 len = 1;
315                         while(len > 0) {
316                                 if ((rc = write(fd, buf,
317                                                 min(len, sizeof(buf))))
318                                     == -1) {
319                                         save_errno = errno;
320                                         perror("write");
321                                         exit(save_errno);
322                                 }
323                                 len -= sizeof(buf);
324                         }
325                         break;
326                 case 'W':
327                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
328                                 mmap_ptr[i] += junk++;
329                         break;
330                 case 'y':
331                         if (fsync(fd) == -1) {
332                                 save_errno = errno;
333                                 perror("fsync");
334                                 exit(save_errno);
335                         }
336                         break;
337                 case 'Y':
338                         if (fdatasync(fd) == -1) {
339                                 save_errno = errno;
340                                 perror("fdatasync");
341                                 exit(save_errno);
342                         }
343                 case 'z':
344                         len = atoi(commands+1);
345                         if (lseek(fd, len, SEEK_SET) == -1) {
346                                 save_errno = errno;
347                                 perror("lseek");
348                                 exit(save_errno);
349                         }
350                         break;
351                 case '0':
352                 case '1':
353                 case '2':
354                 case '3':
355                 case '4':
356                 case '5':
357                 case '6':
358                 case '7':
359                 case '8':
360                 case '9':
361                         break;
362                 default:
363                         fprintf(stderr, "unknown command \"%c\"\n", *commands);
364                         fprintf(stderr, usage, argv[0]);
365                         exit(1);
366                 }
367         }
368
369         return 0;
370 }