Whamcloud - gitweb
b=18696
[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
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
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 "        v  verbose\n"
83 "        w[num] write optional length\n"
84 "        W  write entire mmap-ed region\n"
85 "        y  fsync\n"
86 "        Y  fdatasync\n"
87 "        z[num] seek [optional position, default 0]\n"
88 "        _  wait for signal\n";
89
90 static int usr1_received;
91 void usr1_handler(int unused)
92 {
93         usr1_received = 1;
94 }
95
96 static const char *
97 pop_arg(int argc, char *argv[])
98 {
99         static int cur_arg = 3;
100
101         if (cur_arg >= argc)
102                 return NULL;
103
104         return argv[cur_arg++];
105 }
106
107 struct flag_mapping {
108        const char *string;
109        const int  flag;
110 } flag_table[] = {
111        {"O_RDONLY", O_RDONLY},
112        {"O_WRONLY", O_WRONLY},
113        {"O_RDWR", O_RDWR},
114        {"O_CREAT", O_CREAT},
115        {"O_EXCL", O_EXCL},
116        {"O_NOCTTY", O_NOCTTY},
117        {"O_TRUNC", O_TRUNC},
118        {"O_APPEND", O_APPEND},
119        {"O_NONBLOCK", O_NONBLOCK},
120        {"O_NDELAY", O_NDELAY},
121        {"O_SYNC", O_SYNC},
122 #ifdef O_DIRECT
123        {"O_DIRECT", O_DIRECT},
124 #endif
125        {"O_LARGEFILE", O_LARGEFILE},
126        {"O_DIRECTORY", O_DIRECTORY},
127        {"O_NOFOLLOW", O_NOFOLLOW},
128        {"", -1}
129 };
130
131 int get_flags(char *data, int *rflags)
132 {
133         char *cloned_flags;
134         char *tmp;
135         int flag_set = 0;
136         int flags = 0;
137         int size = 0;
138
139         cloned_flags = strdup(data);
140         if (cloned_flags == NULL) {
141                 fprintf(stderr, "Insufficient memory.\n");
142                 exit(-1);
143         }
144
145         for (tmp = strtok(cloned_flags, ":"); tmp;
146              tmp = strtok(NULL, ":")) {
147                 int i;
148
149                 size = tmp - cloned_flags;
150                 for (i = 0; flag_table[i].flag != -1; i++) {
151                         if (!strcmp(tmp, flag_table[i].string)){
152                                 flags |= flag_table[i].flag;
153                                 size += strlen(flag_table[i].string);
154                                 flag_set = 1;
155                                 break;
156                         }
157                 }
158         }
159         free(cloned_flags);
160
161         if (!flag_set) {
162                 *rflags = O_RDONLY;
163                 return 0;
164         }
165
166         *rflags = flags;
167         return size;
168 }
169
170 #define POP_ARG() (pop_arg(argc, argv))
171 #define min(a,b) ((a)>(b)?(b):(a))
172
173 int main(int argc, char **argv)
174 {
175         char *fname, *commands;
176         const char *newfile;
177         struct stat st;
178         size_t mmap_len = 0, i;
179         unsigned char *mmap_ptr = NULL, junk = 0;
180         int rc, len, fd = -1;
181         int flags;
182         int save_errno;
183         int verbose = 0;
184
185         if (argc < 3) {
186                 fprintf(stderr, usage, argv[0]);
187                 exit(1);
188         }
189
190         memset(&st, 0, sizeof(st));
191         signal(SIGUSR1, usr1_handler);
192
193         fname = argv[1];
194
195         for (commands = argv[2]; *commands; commands++) {
196                 switch (*commands) {
197                 case '_':
198                         if (usr1_received == 0) {
199                                 if (verbose) {
200                                         printf("PAUSING\n");
201                                         fflush(stdout);
202                                 }
203                                 pause();
204                         }
205                         usr1_received = 0;
206                         signal(SIGUSR1, usr1_handler);
207                         break;
208                 case 'c':
209                         if (close(fd) == -1) {
210                                 save_errno = errno;
211                                 perror("close");
212                                 exit(save_errno);
213                         }
214                         fd = -1;
215                         break;
216                 case 'C':
217                         len = atoi(commands+1);
218                         fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
219                                              0, 0, len, 0);
220                         if (fd == -1) {
221                                 save_errno = errno;
222                                 perror("create stripe file");
223                                 exit(save_errno);
224                         }
225                         break;
226                 case 'd':
227                         if (mkdir(fname, 0755) == -1) {
228                                 save_errno = errno;
229                                 perror("mkdir(0755)");
230                                 exit(save_errno);
231                         }
232                         break;
233                 case 'D':
234                         fd = open(fname, O_DIRECTORY);
235                         if (fd == -1) {
236                                 save_errno = errno;
237                                 perror("open(O_DIRECTORY)");
238                                 exit(save_errno);
239                         }
240                         break;
241                 case 'l':
242                         newfile = POP_ARG();
243                         if (!newfile)
244                                 newfile = fname;
245                         if (symlink(fname, newfile)) {
246                                 save_errno = errno;
247                                 perror("symlink()");
248                                 exit(save_errno);
249                         }
250                         break;
251                 case 'L':
252                         newfile = POP_ARG();
253                         if (!newfile)
254                                 newfile = fname;
255                         if (link(fname, newfile)) {
256                                 save_errno = errno;
257                                 perror("symlink()");
258                                 exit(save_errno);
259                         }
260                         break;
261                 case 'm':
262                         if (mknod(fname, S_IFREG | 0644, 0) == -1) {
263                                 save_errno = errno;
264                                 perror("mknod(S_IFREG|0644, 0)");
265                                 exit(save_errno);
266                         }
267                         break;
268                 case 'M':
269                         if (st.st_size == 0) {
270                                 fprintf(stderr, "mmap without preceeding stat, or on"
271                                         " zero length file.\n");
272                                 exit(-1);
273                         }
274                         mmap_len = st.st_size;
275                         mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
276                                         MAP_SHARED, fd, 0);
277                         if (mmap_ptr == MAP_FAILED) {
278                                 save_errno = errno;
279                                 perror("mmap");
280                                 exit(save_errno);
281                         }
282                         break;
283                 case 'N':
284                         newfile = POP_ARG();
285                         if (!newfile)
286                                 newfile = fname;
287                         if (rename (fname, newfile)) {
288                                 save_errno = errno;
289                                 perror("rename()");
290                                 exit(save_errno);
291                         }
292                         break;
293                 case 'O':
294                         fd = open(fname, O_CREAT|O_RDWR, 0644);
295                         if (fd == -1) {
296                                 save_errno = errno;
297                                 perror("open(O_RDWR|O_CREAT)");
298                                 exit(save_errno);
299                         }
300                         break;
301                 case 'o':
302                         len = get_flags(commands+1, &flags);
303                         commands += len;
304                         fd = open(fname, flags);
305                         if (fd == -1) {
306                                 save_errno = errno;
307                                 perror("open");
308                                 exit(save_errno);
309                         }
310                         break;
311                 case 'r':
312                         len = atoi(commands+1);
313                         if (len <= 0)
314                                 len = 1;
315                         if (bufsize < len) {
316                                 buf = realloc(buf, len + ALIGN);
317                                 if (buf == NULL) {
318                                         save_errno = errno;
319                                         perror("allocating buf for read\n");
320                                         exit(save_errno);
321                                 }
322                                 bufsize = len;
323                                 buf_align = (char *)((long)(buf + ALIGN) &
324                                                      ~ALIGN);
325                         }
326                         while (len > 0) {
327                                 rc = read(fd, buf_align, len);
328                                 if (rc == -1) {
329                                         save_errno = errno;
330                                         perror("read");
331                                         exit(save_errno);
332                                 }
333                                 if (rc < len)
334                                         fprintf(stderr, "short read: %u/%u\n",
335                                                 rc, len);
336                                 len -= rc;
337                                 if (verbose >= 2)
338                                         printf("%.*s\n", rc, buf_align);
339                         }
340                         break;
341                 case 'R':
342                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
343                                 junk += mmap_ptr[i];
344                         break;
345                 case 's':
346                         if (stat(fname, &st) == -1) {
347                                 save_errno = errno;
348                                 perror("stat");
349                                 exit(save_errno);
350                         }
351                         break;
352                 case 'S':
353                         if (fstat(fd, &st) == -1) {
354                                 save_errno = errno;
355                                 perror("fstat");
356                                 exit(save_errno);
357                         }
358                         break;
359                 case 't':
360                         if (fchmod(fd, 0) == -1) {
361                                 save_errno = errno;
362                                 perror("fchmod");
363                                 exit(save_errno);
364                         }
365                         break;
366                 case 'T':
367                         len = atoi(commands+1);
368                         if (ftruncate(fd, len) == -1) {
369                                 save_errno = errno;
370                                 printf("ftruncate (%d,%d)\n", fd, len);
371                                 perror("ftruncate");
372                                 exit(save_errno);
373                         }
374                         break;
375                 case 'u':
376                         if (unlink(fname) == -1) {
377                                 save_errno = errno;
378                                 perror("unlink");
379                                 exit(save_errno);
380                         }
381                         break;
382                 case 'U':
383                         if (munmap(mmap_ptr, mmap_len)) {
384                                 save_errno = errno;
385                                 perror("munmap");
386                                 exit(save_errno);
387                         }
388                         break;
389                 case 'v':
390                         verbose++;
391                         break;
392                 case 'w':
393                         len = atoi(commands+1);
394                         if (len <= 0)
395                                 len = 1;
396                         if (bufsize < len) {
397                                 buf = realloc(buf, len + ALIGN);
398                                 if (buf == NULL) {
399                                         save_errno = errno;
400                                         perror("allocating buf for write\n");
401                                         exit(save_errno);
402                                 }
403                                 bufsize = len;
404                                 buf_align = (char *)((long)(buf + ALIGN) &
405                                                      ~ALIGN);
406                                 strncpy(buf_align, msg, bufsize);
407                         }
408                         while (len > 0) {
409                                 rc = write(fd, buf_align, len);
410                                 if (rc == -1) {
411                                         save_errno = errno;
412                                         perror("write");
413                                         exit(save_errno);
414                                 }
415                                 if (rc < len)
416                                         fprintf(stderr, "short write: %u/%u\n",
417                                                 rc, len);
418                                 len -= rc;
419                         }
420                         break;
421                 case 'W':
422                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
423                                 mmap_ptr[i] += junk++;
424                         break;
425                 case 'y':
426                         if (fsync(fd) == -1) {
427                                 save_errno = errno;
428                                 perror("fsync");
429                                 exit(save_errno);
430                         }
431                         break;
432                 case 'Y':
433                         if (fdatasync(fd) == -1) {
434                                 save_errno = errno;
435                                 perror("fdatasync");
436                                 exit(save_errno);
437                         }
438                 case 'z':
439                         len = atoi(commands+1);
440                         if (lseek(fd, len, SEEK_SET) == -1) {
441                                 save_errno = errno;
442                                 perror("lseek");
443                                 exit(save_errno);
444                         }
445                         break;
446                 case '0':
447                 case '1':
448                 case '2':
449                 case '3':
450                 case '4':
451                 case '5':
452                 case '6':
453                 case '7':
454                 case '8':
455                 case '9':
456                         break;
457                 default:
458                         fprintf(stderr, "unknown command \"%c\"\n", *commands);
459                         fprintf(stderr, usage, argv[0]);
460                         exit(1);
461                 }
462         }
463
464         if (buf)
465                 free(buf);
466
467         return 0;
468 }