Whamcloud - gitweb
541e1b0d467b38f5e5e67bc90273b2263a468b07
[fs/lustre-release.git] / lustre / tests / multiop.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, 2013, Intel Corporation.
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 <sys/vfs.h>
48 #include <sys/ioctl.h>
49 #include <signal.h>
50 #include <stdlib.h>
51 #include <unistd.h>
52 #include <semaphore.h>
53 #include <time.h>
54
55 #include <lustre/lustre_idl.h>
56 #include <lustre/lustreapi.h>
57
58 #define T1 "write data before unlink\n"
59 #define T2 "write data after unlink\n"
60 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";
61 char *buf, *buf_align;
62 int bufsize = 0;
63 sem_t sem;
64 #define ALIGN_LEN 65535
65
66 char usage[] =
67 "Usage: %s filename command-sequence [path...]\n"
68 "    command-sequence items:\n"
69 "        c  close\n"
70 "        B[num] call setstripe ioctl to create stripes\n"
71 "        C[num] create with optional stripes\n"
72 "        d  mkdir\n"
73 "        D  open(O_DIRECTORY)\n"
74 "        f  statfs\n"
75 "        F  print FID\n"
76 "        G gid get grouplock\n"
77 "        g gid put grouplock\n"
78 "        K  link path to filename\n"
79 "        L  link\n"
80 "        l  symlink filename to path\n"
81 "        m  mknod\n"
82 "        M  rw mmap to EOF (must open and stat prior)\n"
83 "        n  rename path to filename\n"
84 "        N  rename filename to path\n"
85 "        o  open(O_RDONLY)\n"
86 "        O  open(O_CREAT|O_RDWR)\n"
87 "        r[num] read [optional length]\n"
88 "        R  reference entire mmap-ed region\n"
89 "        s  stat\n"
90 "        S  fstat\n"
91 "        t  fchmod\n"
92 "        T[num] ftruncate [optional position, default 0]\n"
93 "        u  unlink\n"
94 "        U  munmap\n"
95 "        v  verbose\n"
96 "        V  open a volatile file\n"
97 "        w[num] write optional length\n"
98 "        x  get file data version\n"
99 "        W  write entire mmap-ed region\n"
100 "        y  fsync\n"
101 "        Y  fdatasync\n"
102 "        z[num] seek [optional position, default 0]\n"
103 "        _  wait for signal\n";
104
105 void usr1_handler(int unused)
106 {
107         int saved_errno = errno;
108
109         /*
110          * signal(7): POSIX.1-2004 ...requires an implementation to guarantee
111          * that the following functions can be safely called inside a signal
112          * handler:
113          *            sem_post()
114          */
115         sem_post(&sem);
116
117         errno = saved_errno;
118 }
119
120 static const char *
121 pop_arg(int argc, char *argv[])
122 {
123         static int cur_arg = 3;
124
125         if (cur_arg >= argc)
126                 return NULL;
127
128         return argv[cur_arg++];
129 }
130
131 struct flag_mapping {
132         const char *string;
133         const int  flag;
134 } flag_table[] = {
135         {"O_RDONLY", O_RDONLY},
136         {"O_WRONLY", O_WRONLY},
137         {"O_RDWR", O_RDWR},
138         {"O_CREAT", O_CREAT},
139         {"O_EXCL", O_EXCL},
140         {"O_NOCTTY", O_NOCTTY},
141         {"O_TRUNC", O_TRUNC},
142         {"O_APPEND", O_APPEND},
143         {"O_NONBLOCK", O_NONBLOCK},
144         {"O_NDELAY", O_NDELAY},
145         {"O_SYNC", O_SYNC},
146 #ifdef O_DIRECT
147         {"O_DIRECT", O_DIRECT},
148 #endif
149         {"O_LARGEFILE", O_LARGEFILE},
150         {"O_DIRECTORY", O_DIRECTORY},
151         {"O_NOFOLLOW", O_NOFOLLOW},
152         {"O_LOV_DELAY_CREATE", O_LOV_DELAY_CREATE},
153         {"", -1}
154 };
155
156 int get_flags(char *data, int *rflags)
157 {
158         char *cloned_flags;
159         char *tmp;
160         int flag_set = 0;
161         int flags = 0;
162         int size = 0;
163
164         cloned_flags = strdup(data);
165         if (cloned_flags == NULL) {
166                 fprintf(stderr, "Insufficient memory.\n");
167                 exit(-1);
168         }
169
170         for (tmp = strtok(cloned_flags, ":"); tmp;
171              tmp = strtok(NULL, ":")) {
172                 int i;
173
174                 size = tmp - cloned_flags;
175                 for (i = 0; flag_table[i].flag != -1; i++) {
176                         if (!strcmp(tmp, flag_table[i].string)){
177                                 flags |= flag_table[i].flag;
178                                 size += strlen(flag_table[i].string);
179                                 flag_set = 1;
180                                 break;
181                         }
182                 }
183         }
184         free(cloned_flags);
185
186         if (!flag_set) {
187                 *rflags = O_RDONLY;
188                 return 0;
189         }
190
191         *rflags = flags;
192         return size;
193 }
194
195 #define POP_ARG() (pop_arg(argc, argv))
196
197 int main(int argc, char **argv)
198 {
199         char                    *fname, *commands;
200         const char              *newfile;
201         const char              *oldpath;
202         struct stat              st;
203         struct statfs            stfs;
204         size_t                   mmap_len = 0, i;
205         unsigned char           *mmap_ptr = NULL, junk = 0;
206         int                      rc, len, fd = -1;
207         int                      flags;
208         int                      save_errno;
209         int                      verbose = 0;
210         int                      gid = 0;
211         lustre_fid               fid;
212         struct timespec          ts;
213         struct lov_user_md_v3    lum;
214         __u64                    dv;
215
216         if (argc < 3) {
217                 fprintf(stderr, usage, argv[0]);
218                 exit(1);
219         }
220
221         memset(&st, 0, sizeof(st));
222         sem_init(&sem, 0, 0);
223         /* use sigaction instead of signal to avoid SA_ONESHOT semantics */
224         sigaction(SIGUSR1, &(const struct sigaction){.sa_handler = &usr1_handler},
225                   NULL);
226
227         fname = argv[1];
228
229         for (commands = argv[2]; *commands; commands++) {
230                 switch (*commands) {
231                 case '_':
232                         if (verbose) {
233                                 printf("PAUSING\n");
234                                 fflush(stdout);
235                         }
236                         len = atoi(commands+1);
237                         if (len <= 0)
238                                 len = 3600; /* 1 hour */
239                         ts.tv_sec = time(NULL) + len;
240                         ts.tv_nsec = 0;
241                         while (sem_timedwait(&sem, &ts) < 0 && errno == EINTR);
242                         break;
243                 case 'c':
244                         if (close(fd) == -1) {
245                                 save_errno = errno;
246                                 perror("close");
247                                 exit(save_errno);
248                         }
249                         fd = -1;
250                         break;
251                 case 'B':
252                         lum = (struct lov_user_md_v3) {
253                                 .lmm_magic = LOV_USER_MAGIC_V3,
254                                 .lmm_stripe_count = atoi(commands + 1),
255                         };
256
257                         if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum) < 0) {
258                                 save_errno = errno;
259                                 perror("LL_IOC_LOV_SETSTRIPE");
260                                 exit(save_errno);
261                         }
262                         break;
263                 case 'C':
264                         len = atoi(commands+1);
265                         fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
266                                              0, 0, len, 0);
267                         if (fd == -1) {
268                                 save_errno = errno;
269                                 perror("create stripe file");
270                                 exit(save_errno);
271                         }
272                         break;
273                 case 'd':
274                         if (mkdir(fname, 0755) == -1) {
275                                 save_errno = errno;
276                                 perror("mkdir(0755)");
277                                 exit(save_errno);
278                         }
279                         break;
280                 case 'D':
281                         fd = open(fname, O_DIRECTORY);
282                         if (fd == -1) {
283                                 save_errno = errno;
284                                 perror("open(O_DIRECTORY)");
285                                 exit(save_errno);
286                         }
287                         break;
288                 case 'f':
289                         if (statfs(fname, &stfs) == -1) {
290                                 save_errno = errno;
291                                 perror("statfs()");
292                                 exit(save_errno);
293                         }
294                         break;
295                 case 'F':
296                         if (fd == -1)
297                                 rc = llapi_path2fid(fname, &fid);
298                         else
299                                 rc = llapi_fd2fid(fd, &fid);
300                         if (rc != 0)
301                                 fprintf(stderr,
302                                         "llapi_path/fd2fid() on %d, rc=%d\n",
303                                         fd, rc);
304                         else
305                                 printf(DFID"\n", PFID(&fid));
306                         break;
307                 case 'G':
308                         gid = atoi(commands+1);
309                         if (ioctl(fd, LL_IOC_GROUP_LOCK, gid) == -1) {
310                                 save_errno = errno;
311                                 perror("ioctl(GROUP_LOCK)");
312                                 exit(save_errno);
313                         }
314                         break;
315                 case 'g':
316                         gid = atoi(commands+1);
317                         if (ioctl(fd, LL_IOC_GROUP_UNLOCK, gid) == -1) {
318                                 save_errno = errno;
319                                 perror("ioctl(GROUP_UNLOCK)");
320                                 exit(save_errno);
321                         }
322                         break;
323                 case 'H':
324                         len = atoi(commands+1);
325                         fd = llapi_file_open(fname, O_CREAT | O_WRONLY,
326                                 0644, 0, 0, len,
327                                 LOV_PATTERN_RAID0 | LOV_PATTERN_F_RELEASED);
328                         if (fd == -1) {
329                                 save_errno = errno;
330                                 perror("create stripe file");
331                                 exit(save_errno);
332                         }
333                         break;
334                 case 'K':
335                         oldpath = POP_ARG();
336                         if (oldpath == NULL)
337                                 oldpath = fname;
338
339                         if (link(oldpath, fname)) {
340                                 save_errno = errno;
341                                 perror("link()");
342                                 exit(save_errno);
343                         }
344                         break;
345                 case 'l':
346                         newfile = POP_ARG();
347                         if (!newfile)
348                                 newfile = fname;
349                         if (symlink(fname, newfile)) {
350                                 save_errno = errno;
351                                 perror("symlink()");
352                                 exit(save_errno);
353                         }
354                         break;
355                 case 'L':
356                         newfile = POP_ARG();
357                         if (newfile == NULL)
358                                 newfile = fname;
359
360                         if (link(fname, newfile)) {
361                                 save_errno = errno;
362                                 perror("link()");
363                                 exit(save_errno);
364                         }
365                         break;
366                 case 'm':
367                         if (mknod(fname, S_IFREG | 0644, 0) == -1) {
368                                 save_errno = errno;
369                                 perror("mknod(S_IFREG|0644, 0)");
370                                 exit(save_errno);
371                         }
372                         break;
373                 case 'M':
374                         if (st.st_size == 0) {
375                                 fprintf(stderr, "mmap without preceeding stat, or on"
376                                         " zero length file.\n");
377                                 exit(-1);
378                         }
379                         mmap_len = st.st_size;
380                         mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
381                                         MAP_SHARED, fd, 0);
382                         if (mmap_ptr == MAP_FAILED) {
383                                 save_errno = errno;
384                                 perror("mmap");
385                                 exit(save_errno);
386                         }
387                         break;
388                 case 'n':
389                         oldpath = POP_ARG();
390                         if (oldpath == NULL)
391                                 oldpath = fname;
392
393                         if (rename(oldpath, fname) < 0) {
394                                 save_errno = errno;
395                                 perror("rename()");
396                                 exit(save_errno);
397                         }
398                         break;
399                 case 'N':
400                         newfile = POP_ARG();
401                         if (!newfile)
402                                 newfile = fname;
403                         if (rename (fname, newfile)) {
404                                 save_errno = errno;
405                                 perror("rename()");
406                                 exit(save_errno);
407                         }
408                         break;
409                 case 'O':
410                         fd = open(fname, O_CREAT|O_RDWR, 0644);
411                         if (fd == -1) {
412                                 save_errno = errno;
413                                 perror("open(O_RDWR|O_CREAT)");
414                                 exit(save_errno);
415                         }
416                         break;
417                 case 'o':
418                         len = get_flags(commands+1, &flags);
419                         commands += len;
420                         if (flags & O_CREAT)
421                                 fd = open(fname, flags, 0666);
422                         else
423                                 fd = open(fname, flags);
424                         if (fd == -1) {
425                                 save_errno = errno;
426                                 perror("open");
427                                 exit(save_errno);
428                         }
429                         break;
430                 case 'r':
431                         len = atoi(commands+1);
432                         if (len <= 0)
433                                 len = 1;
434                         if (bufsize < len) {
435                                 buf = realloc(buf, len + ALIGN_LEN);
436                                 if (buf == NULL) {
437                                         save_errno = errno;
438                                         perror("allocating buf for read\n");
439                                         exit(save_errno);
440                                 }
441                                 bufsize = len;
442                                 buf_align = (char *)((long)(buf + ALIGN_LEN) &
443                                                      ~ALIGN_LEN);
444                         }
445                         while (len > 0) {
446                                 rc = read(fd, buf_align, len);
447                                 if (rc == -1) {
448                                         save_errno = errno;
449                                         perror("read");
450                                         exit(save_errno);
451                                 }
452                                 if (rc < len) {
453                                         fprintf(stderr, "short read: %u/%u\n",
454                                                 rc, len);
455                                         if (rc == 0)
456                                                 exit(ENODATA);
457                                 }
458                                 len -= rc;
459                                 if (verbose >= 2)
460                                         printf("%.*s\n", rc, buf_align);
461                         }
462                         break;
463                 case 'R':
464                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
465                                 junk += mmap_ptr[i];
466                         break;
467                 case 's':
468                         if (stat(fname, &st) == -1) {
469                                 save_errno = errno;
470                                 perror("stat");
471                                 exit(save_errno);
472                         }
473                         break;
474                 case 'S':
475                         if (fstat(fd, &st) == -1) {
476                                 save_errno = errno;
477                                 perror("fstat");
478                                 exit(save_errno);
479                         }
480                         break;
481                 case 't':
482                         if (fchmod(fd, 0) == -1) {
483                                 save_errno = errno;
484                                 perror("fchmod");
485                                 exit(save_errno);
486                         }
487                         break;
488                 case 'T':
489                         len = atoi(commands+1);
490                         if (ftruncate(fd, len) == -1) {
491                                 save_errno = errno;
492                                 printf("ftruncate (%d,%d)\n", fd, len);
493                                 perror("ftruncate");
494                                 exit(save_errno);
495                         }
496                         break;
497                 case 'u':
498                         if (unlink(fname) == -1) {
499                                 save_errno = errno;
500                                 perror("unlink");
501                                 exit(save_errno);
502                         }
503                         break;
504                 case 'U':
505                         if (munmap(mmap_ptr, mmap_len)) {
506                                 save_errno = errno;
507                                 perror("munmap");
508                                 exit(save_errno);
509                         }
510                         break;
511                 case 'v':
512                         verbose++;
513                         break;
514                 case 'V':
515                         len = get_flags(commands + 1, &flags);
516                         commands += len;
517                         fd = llapi_create_volatile(fname, flags);
518                         if (fd < 0) {
519                                 perror("llapi_create_volatile");
520                                 exit(fd);
521                         }
522                         break;
523                 case 'w':
524                         len = atoi(commands+1);
525                         if (len <= 0)
526                                 len = 1;
527                         if (bufsize < len) {
528                                 buf = realloc(buf, len + ALIGN_LEN);
529                                 if (buf == NULL) {
530                                         save_errno = errno;
531                                         perror("allocating buf for write\n");
532                                         exit(save_errno);
533                                 }
534                                 bufsize = len;
535                                 buf_align = (char *)((long)(buf + ALIGN_LEN) &
536                                                      ~ALIGN_LEN);
537                                 strncpy(buf_align, msg, bufsize);
538                         }
539                         while (len > 0) {
540                                 rc = write(fd, buf_align, len);
541                                 if (rc == -1) {
542                                         save_errno = errno;
543                                         perror("write");
544                                         exit(save_errno);
545                                 }
546                                 if (rc < len)
547                                         fprintf(stderr, "short write: %u/%u\n",
548                                                 rc, len);
549                                 len -= rc;
550                         }
551                         break;
552                 case 'W':
553                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
554                                 mmap_ptr[i] += junk++;
555                         break;
556                 case 'x':
557                         rc = llapi_get_data_version(fd, &dv, 0);
558                         if (rc) {
559                                 fprintf(stderr, "cannot get file data version"
560                                         " %d\n", rc);
561                                 exit(-rc);
562                         }
563                         printf("dataversion is "LPU64"\n", dv);
564                         break;
565                 case 'y':
566                         if (fsync(fd) == -1) {
567                                 save_errno = errno;
568                                 perror("fsync");
569                                 exit(save_errno);
570                         }
571                         break;
572                 case 'Y':
573                         if (fdatasync(fd) == -1) {
574                                 save_errno = errno;
575                                 perror("fdatasync");
576                                 exit(save_errno);
577                         }
578                 case 'z':
579                         len = atoi(commands+1);
580                         if (lseek(fd, len, SEEK_SET) == -1) {
581                                 save_errno = errno;
582                                 perror("lseek");
583                                 exit(save_errno);
584                         }
585                         break;
586                 case '-':
587                 case '0':
588                 case '1':
589                 case '2':
590                 case '3':
591                 case '4':
592                 case '5':
593                 case '6':
594                 case '7':
595                 case '8':
596                 case '9':
597                         break;
598                 default:
599                         fprintf(stderr, "unknown command \"%c\"\n", *commands);
600                         fprintf(stderr, usage, argv[0]);
601                         exit(1);
602                 }
603         }
604
605         if (buf)
606                 free(buf);
607
608         return 0;
609 }