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