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