Whamcloud - gitweb
b=15699
[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         signal(SIGUSR1, usr1_handler);
191
192         fname = argv[1];
193
194         for (commands = argv[2]; *commands; commands++) {
195                 switch (*commands) {
196                 case '_':
197                         if (usr1_received == 0) {
198                                 if (verbose) {
199                                         printf("PAUSING\n");
200                                         fflush(stdout);
201                                 }
202                                 pause();
203                         }
204                         usr1_received = 0;
205                         signal(SIGUSR1, usr1_handler);
206                         break;
207                 case 'c':
208                         if (close(fd) == -1) {
209                                 save_errno = errno;
210                                 perror("close");
211                                 exit(save_errno);
212                         }
213                         fd = -1;
214                         break;
215                 case 'C':
216                         len = atoi(commands+1);
217                         fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
218                                              0, 0, len, 0);
219                         if (fd == -1) {
220                                 save_errno = errno;
221                                 perror("create stripe file");
222                                 exit(save_errno);
223                         }
224                         break;
225                 case 'd':
226                         if (mkdir(fname, 0755) == -1) {
227                                 save_errno = errno;
228                                 perror("mkdir(0755)");
229                                 exit(save_errno);
230                         }
231                         break;
232                 case 'D':
233                         fd = open(fname, O_DIRECTORY);
234                         if (fd == -1) {
235                                 save_errno = errno;
236                                 perror("open(O_DIRECTORY)");
237                                 exit(save_errno);
238                         }
239                         break;
240                 case 'l':
241                         newfile = POP_ARG();
242                         if (!newfile)
243                                 newfile = fname;
244                         if (symlink(fname, newfile)) {
245                                 save_errno = errno;
246                                 perror("symlink()");
247                                 exit(save_errno);
248                         }
249                         break;
250                 case 'L':
251                         newfile = POP_ARG();
252                         if (!newfile)
253                                 newfile = fname;
254                         if (link(fname, newfile)) {
255                                 save_errno = errno;
256                                 perror("symlink()");
257                                 exit(save_errno);
258                         }
259                         break;
260                 case 'm':
261                         if (mknod(fname, S_IFREG | 0644, 0) == -1) {
262                                 save_errno = errno;
263                                 perror("mknod(S_IFREG|0644, 0)");
264                                 exit(save_errno);
265                         }
266                         break;
267                 case 'M':
268                         mmap_len = st.st_size;
269                         mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
270                                         MAP_SHARED, fd, 0);
271                         if (mmap_ptr == MAP_FAILED) {
272                                 save_errno = errno;
273                                 perror("mmap");
274                                 exit(save_errno);
275                         }
276                         break;
277                 case 'N':
278                         newfile = POP_ARG();
279                         if (!newfile)
280                                 newfile = fname;
281                         if (rename (fname, newfile)) {
282                                 save_errno = errno;
283                                 perror("rename()");
284                                 exit(save_errno);
285                         }
286                         break;
287                 case 'O':
288                         fd = open(fname, O_CREAT|O_RDWR, 0644);
289                         if (fd == -1) {
290                                 save_errno = errno;
291                                 perror("open(O_RDWR|O_CREAT)");
292                                 exit(save_errno);
293                         }
294                         break;
295                 case 'o':
296                         len = get_flags(commands+1, &flags);
297                         commands += len;
298                         fd = open(fname, flags);
299                         if (fd == -1) {
300                                 save_errno = errno;
301                                 perror("open");
302                                 exit(save_errno);
303                         }
304                         break;
305                 case 'r':
306                         len = atoi(commands+1);
307                         if (len <= 0)
308                                 len = 1;
309                         if (bufsize < len) {
310                                 buf = realloc(buf, len + ALIGN);
311                                 if (buf == NULL) {
312                                         save_errno = errno;
313                                         perror("allocating buf for read\n");
314                                         exit(save_errno);
315                                 }
316                                 bufsize = len;
317                                 buf_align = (char *)((long)(buf + ALIGN) &
318                                                      ~ALIGN);
319                         }
320                         while (len > 0) {
321                                 rc = read(fd, buf_align, len);
322                                 if (rc == -1) {
323                                         save_errno = errno;
324                                         perror("read");
325                                         exit(save_errno);
326                                 }
327                                 if (rc < len)
328                                         fprintf(stderr, "short read: %u/%u\n",
329                                                 rc, len);
330                                 len -= rc;
331                                 if (verbose >= 2)
332                                         printf("%.*s\n", rc, buf_align);
333                         }
334                         break;
335                 case 'R':
336                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
337                                 junk += mmap_ptr[i];
338                         break;
339                 case 's':
340                         if (stat(fname, &st) == -1) {
341                                 save_errno = errno;
342                                 perror("stat");
343                                 exit(save_errno);
344                         }
345                         break;
346                 case 'S':
347                         if (fstat(fd, &st) == -1) {
348                                 save_errno = errno;
349                                 perror("fstat");
350                                 exit(save_errno);
351                         }
352                         break;
353                 case 't':
354                         if (fchmod(fd, 0) == -1) {
355                                 save_errno = errno;
356                                 perror("fchmod");
357                                 exit(save_errno);
358                         }
359                         break;
360                 case 'T':
361                         len = atoi(commands+1);
362                         if (ftruncate(fd, len) == -1) {
363                                 save_errno = errno;
364                                 printf("ftruncate (%d,%d)\n", fd, len);
365                                 perror("ftruncate");
366                                 exit(save_errno);
367                         }
368                         break;
369                 case 'u':
370                         if (unlink(fname) == -1) {
371                                 save_errno = errno;
372                                 perror("unlink");
373                                 exit(save_errno);
374                         }
375                         break;
376                 case 'U':
377                         if (munmap(mmap_ptr, mmap_len)) {
378                                 save_errno = errno;
379                                 perror("munmap");
380                                 exit(save_errno);
381                         }
382                         break;
383                 case 'v':
384                         verbose++;
385                         break;
386                 case 'w':
387                         len = atoi(commands+1);
388                         if (len <= 0)
389                                 len = 1;
390                         if (bufsize < len) {
391                                 buf = realloc(buf, len + ALIGN);
392                                 if (buf == NULL) {
393                                         save_errno = errno;
394                                         perror("allocating buf for write\n");
395                                         exit(save_errno);
396                                 }
397                                 bufsize = len;
398                                 buf_align = (char *)((long)(buf + ALIGN) &
399                                                      ~ALIGN);
400                                 strncpy(buf_align, msg, bufsize);
401                         }
402                         while (len > 0) {
403                                 rc = write(fd, buf_align, len);
404                                 if (rc == -1) {
405                                         save_errno = errno;
406                                         perror("write");
407                                         exit(save_errno);
408                                 }
409                                 if (rc < len)
410                                         fprintf(stderr, "short write: %u/%u\n",
411                                                 rc, len);
412                                 len -= rc;
413                         }
414                         break;
415                 case 'W':
416                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
417                                 mmap_ptr[i] += junk++;
418                         break;
419                 case 'y':
420                         if (fsync(fd) == -1) {
421                                 save_errno = errno;
422                                 perror("fsync");
423                                 exit(save_errno);
424                         }
425                         break;
426                 case 'Y':
427                         if (fdatasync(fd) == -1) {
428                                 save_errno = errno;
429                                 perror("fdatasync");
430                                 exit(save_errno);
431                         }
432                 case 'z':
433                         len = atoi(commands+1);
434                         if (lseek(fd, len, SEEK_SET) == -1) {
435                                 save_errno = errno;
436                                 perror("lseek");
437                                 exit(save_errno);
438                         }
439                         break;
440                 case '0':
441                 case '1':
442                 case '2':
443                 case '3':
444                 case '4':
445                 case '5':
446                 case '6':
447                 case '7':
448                 case '8':
449                 case '9':
450                         break;
451                 default:
452                         fprintf(stderr, "unknown command \"%c\"\n", *commands);
453                         fprintf(stderr, usage, argv[0]);
454                         exit(1);
455                 }
456         }
457
458         if (buf)
459                 free(buf);
460
461         return 0;
462 }