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