Whamcloud - gitweb
LU-8150 mdt: Track open+create as mknod
[fs/lustre-release.git] / lustre / tests / multiop.c
index 814bd88..40a8cb4 100644 (file)
@@ -27,7 +27,7 @@
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2012, Intel Corporation.
+ * Copyright (c) 2012, 2015, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
 #ifndef _GNU_SOURCE
 #define _GNU_SOURCE /* pull in O_DIRECTORY in bits/fcntl.h */
 #endif
-#include <stdio.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
 #include <string.h>
-#include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
 #include <sys/vfs.h>
 #include <sys/ioctl.h>
+#include <sys/xattr.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <semaphore.h>
 #include <time.h>
+#include <err.h>
 
 #include <lustre/lustre_idl.h>
 #include <lustre/lustreapi.h>
@@ -62,41 +65,51 @@ char *buf, *buf_align;
 int bufsize = 0;
 sem_t sem;
 #define ALIGN_LEN 65535
+#define XATTR "user.multiop"
 
 char usage[] =
-"Usage: %s filename command-sequence\n"
+"Usage: %s filename command-sequence [path...]\n"
 "    command-sequence items:\n"
-"        c  close\n"
-"        C[num] create with optional stripes\n"
-"        d  mkdir\n"
-"        D  open(O_DIRECTORY)\n"
-"        f  statfs\n"
+"       A  fsetxattr(\"user.multiop\")\n"
+"       a  fgetxattr(\"user.multiop\")\n"
+"       c  close\n"
+"       B[num] call setstripe ioctl to create stripes\n"
+"       C[num] create with optional stripes\n"
+"       d  mkdir\n"
+"       D  open(O_DIRECTORY)\n"
+"       e[R|W|U] apply lease. R: Read; W: Write; U: Unlock\n"
+"       E[+|-] get lease. +/-: expect lease to (not) exist\n"
+"       f  statfs\n"
 "       F  print FID\n"
-"        G gid get grouplock\n"
-"        g gid put grouplock\n"
-"        L  link\n"
-"        l  symlink\n"
-"        m  mknod\n"
-"        M  rw mmap to EOF (must open and stat prior)\n"
-"        N  rename\n"
-"        o  open(O_RDONLY)\n"
-"        O  open(O_CREAT|O_RDWR)\n"
-"        r[num] read [optional length]\n"
-"        R  reference entire mmap-ed region\n"
-"        s  stat\n"
-"        S  fstat\n"
-"        t  fchmod\n"
-"        T[num] ftruncate [optional position, default 0]\n"
-"        u  unlink\n"
-"        U  munmap\n"
-"        v  verbose\n"
+"       H[num] create HSM released file with num stripes\n"
+"       G gid get grouplock\n"
+"       g gid put grouplock\n"
+"       K  link path to filename\n"
+"       L  link\n"
+"       l  symlink filename to path\n"
+"       m  mknod\n"
+"       M  rw mmap to EOF (must open and stat prior)\n"
+"       n  rename path to filename\n"
+"       N  rename filename to path\n"
+"       o  open(O_RDONLY)\n"
+"       O  open(O_CREAT|O_RDWR)\n"
+"       r[num] read [optional length]\n"
+"       R  reference entire mmap-ed region\n"
+"       s  stat\n"
+"       S  fstat\n"
+"       t  fchmod\n"
+"       T[num] ftruncate [optional position, default 0]\n"
+"       u  unlink\n"
+"       U  munmap\n"
+"       v  verbose\n"
 "       V  open a volatile file\n"
-"        w[num] write optional length\n"
-"        W  write entire mmap-ed region\n"
-"        y  fsync\n"
-"        Y  fdatasync\n"
-"        z[num] seek [optional position, default 0]\n"
-"        _  wait for signal\n";
+"       w[num] write optional length\n"
+"       x  get file data version\n"
+"       W  write entire mmap-ed region\n"
+"       y  fsync\n"
+"       Y  fdatasync\n"
+"       z[num] seek [optional position, default 0]\n"
+"       _  wait for signal\n";
 
 void usr1_handler(int unused)
 {
@@ -125,27 +138,31 @@ pop_arg(int argc, char *argv[])
 }
 
 struct flag_mapping {
-       const char *string;
-       const int  flag;
+       const char *string;
+       const int  flag;
 } flag_table[] = {
-       {"O_RDONLY", O_RDONLY},
-       {"O_WRONLY", O_WRONLY},
-       {"O_RDWR", O_RDWR},
-       {"O_CREAT", O_CREAT},
-       {"O_EXCL", O_EXCL},
-       {"O_NOCTTY", O_NOCTTY},
-       {"O_TRUNC", O_TRUNC},
-       {"O_APPEND", O_APPEND},
-       {"O_NONBLOCK", O_NONBLOCK},
-       {"O_NDELAY", O_NDELAY},
-       {"O_SYNC", O_SYNC},
+       {"O_RDONLY", O_RDONLY},
+       {"O_WRONLY", O_WRONLY},
+       {"O_RDWR", O_RDWR},
+       {"O_CREAT", O_CREAT},
+       {"O_EXCL", O_EXCL},
+       {"O_NOCTTY", O_NOCTTY},
+       {"O_TRUNC", O_TRUNC},
+       {"O_APPEND", O_APPEND},
+       {"O_NONBLOCK", O_NONBLOCK},
+       {"O_NDELAY", O_NDELAY},
+       {"O_SYNC", O_SYNC},
 #ifdef O_DIRECT
-       {"O_DIRECT", O_DIRECT},
+       {"O_DIRECT", O_DIRECT},
 #endif
-       {"O_LARGEFILE", O_LARGEFILE},
-       {"O_DIRECTORY", O_DIRECTORY},
-       {"O_NOFOLLOW", O_NOFOLLOW},
-       {"", -1}
+#ifdef O_NOATIME
+       {"O_NOATIME", O_NOATIME},
+#endif
+       {"O_LARGEFILE", O_LARGEFILE},
+       {"O_DIRECTORY", O_DIRECTORY},
+       {"O_NOFOLLOW", O_NOFOLLOW},
+       {"O_LOV_DELAY_CREATE", O_LOV_DELAY_CREATE},
+       {"", -1}
 };
 
 int get_flags(char *data, int *rflags)
@@ -191,19 +208,22 @@ int get_flags(char *data, int *rflags)
 
 int main(int argc, char **argv)
 {
-       char            *fname, *commands;
-       const char      *newfile;
-       struct stat      st;
-       struct statfs    stfs;
-       size_t           mmap_len = 0, i;
-       unsigned char   *mmap_ptr = NULL, junk = 0;
-       int              rc, len, fd = -1;
-       int              flags;
-       int              save_errno;
-       int              verbose = 0;
-       int              gid = 0;
-       lustre_fid       fid;
-       struct timespec  ts;
+       char                    *fname, *commands;
+       const char              *newfile;
+       const char              *oldpath;
+       struct stat              st;
+       struct statfs            stfs;
+       size_t                   mmap_len = 0, i;
+       unsigned char           *mmap_ptr = NULL, junk = 0;
+       int                      rc, len, fd = -1;
+       int                      flags;
+       int                      save_errno;
+       int                      verbose = 0;
+       int                      gid = 0;
+       lustre_fid               fid;
+       struct timespec          ts;
+       struct lov_user_md_v3    lum;
+       __u64                    dv;
 
         if (argc < 3) {
                 fprintf(stderr, usage, argv[0]);
@@ -232,6 +252,20 @@ int main(int argc, char **argv)
                        ts.tv_nsec = 0;
                         while (sem_timedwait(&sem, &ts) < 0 && errno == EINTR);
                         break;
+               case 'A':
+                       if (fsetxattr(fd, XATTR, "multiop", 8, 0)) {
+                               save_errno = errno;
+                               perror("fsetxattr");
+                               exit(save_errno);
+                       }
+                       break;
+               case 'a':
+                       if (fgetxattr(fd, XATTR, NULL, 0) == -1) {
+                               save_errno = errno;
+                               perror("fgetxattr");
+                               exit(save_errno);
+                       }
+                       break;
                 case 'c':
                         if (close(fd) == -1) {
                                 save_errno = errno;
@@ -240,6 +274,18 @@ int main(int argc, char **argv)
                         }
                         fd = -1;
                         break;
+               case 'B':
+                       lum = (struct lov_user_md_v3) {
+                               .lmm_magic = LOV_USER_MAGIC_V3,
+                               .lmm_stripe_count = atoi(commands + 1),
+                       };
+
+                       if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum) < 0) {
+                               save_errno = errno;
+                               perror("LL_IOC_LOV_SETSTRIPE");
+                               exit(save_errno);
+                       }
+                       break;
                 case 'C':
                         len = atoi(commands+1);
                         fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
@@ -265,13 +311,71 @@ int main(int argc, char **argv)
                                 exit(save_errno);
                         }
                         break;
-                case 'f':
-                        if (statfs(fname, &stfs) == -1) {
-                                save_errno = errno;
-                                perror("statfs()");
-                                exit(save_errno);
-                        }
-                        break;
+               case 'e':
+                       commands++;
+                       switch (*commands) {
+                       case 'U':
+                               flags = LL_LEASE_UNLCK;
+                               break;
+                       case 'R':
+                               flags = LL_LEASE_RDLCK;
+                               break;
+                       case 'W':
+                               flags = LL_LEASE_WRLCK;
+                               break;
+                       default:
+                               errx(-1, "unknown mode: %c", *commands);
+                       }
+
+                       rc = ioctl(fd, LL_IOC_SET_LEASE, flags);
+                       if (rc < 0)
+                               err(errno, "apply lease error");
+
+                       if (flags != LL_LEASE_UNLCK)
+                               break;
+
+                       /* F_UNLCK, interpret return code */
+                       if (rc > 0) {
+                               const char *str = "unknown";
+                               if (rc == LL_LEASE_RDLCK)
+                                       str = "read";
+                               else if (rc == LL_LEASE_WRLCK)
+                                       str = "write";
+                               fprintf(stdout, "%s lease(%d) released.\n",
+                                       str, rc);
+                       } else if (rc == 0) {
+                               fprintf(stdout, "lease already broken.\n");
+                       }
+                       break;
+               case 'E':
+                       commands++;
+                       if (*commands != '-' && *commands != '+')
+                               errx(-1, "unknown mode: %c\n", *commands);
+
+                       rc = ioctl(fd, LL_IOC_GET_LEASE);
+                       if (rc > 0) {
+                               const char *str = "unknown";
+
+                               if (rc == LL_LEASE_RDLCK)
+                                       str = "read";
+                               else if (rc == LL_LEASE_WRLCK)
+                                       str = "write";
+                               fprintf(stdout, "%s lease(%d) has applied.\n",
+                                       str, rc);
+                               if (*commands == '-')
+                                       errx(-1, "expect lease to not exist");
+                       } else if (rc == 0) {
+                               fprintf(stdout, "no lease applied.\n");
+                               if (*commands == '+')
+                                       errx(-1, "expect lease exists");
+                       } else {
+                               err(errno, "free lease error");
+                       }
+                       break;
+               case 'f':
+                       if (statfs(fname, &stfs) == -1)
+                               errx(-1, "statfs()");
+                       break;
                case 'F':
                        if (fd == -1)
                                rc = llapi_path2fid(fname, &fid);
@@ -300,6 +404,28 @@ int main(int argc, char **argv)
                                 exit(save_errno);
                         }
                         break;
+               case 'H':
+                       len = atoi(commands+1);
+                       fd = llapi_file_open(fname, O_CREAT | O_WRONLY,
+                               0644, 0, 0, len,
+                               LOV_PATTERN_RAID0 | LOV_PATTERN_F_RELEASED);
+                       if (fd == -1) {
+                               save_errno = errno;
+                               perror("create stripe file");
+                               exit(save_errno);
+                       }
+                       break;
+               case 'K':
+                       oldpath = POP_ARG();
+                       if (oldpath == NULL)
+                               oldpath = fname;
+
+                       if (link(oldpath, fname)) {
+                               save_errno = errno;
+                               perror("link()");
+                               exit(save_errno);
+                       }
+                       break;
                 case 'l':
                         newfile = POP_ARG();
                         if (!newfile)
@@ -310,16 +436,17 @@ int main(int argc, char **argv)
                                 exit(save_errno);
                         }
                         break;
-                case 'L':
-                        newfile = POP_ARG();
-                        if (!newfile)
-                                newfile = fname;
-                        if (link(fname, newfile)) {
-                                save_errno = errno;
-                                perror("symlink()");
-                                exit(save_errno);
-                        }
-                        break;
+               case 'L':
+                       newfile = POP_ARG();
+                       if (newfile == NULL)
+                               newfile = fname;
+
+                       if (link(fname, newfile)) {
+                               save_errno = errno;
+                               perror("link()");
+                               exit(save_errno);
+                       }
+                       break;
                 case 'm':
                         if (mknod(fname, S_IFREG | 0644, 0) == -1) {
                                 save_errno = errno;
@@ -342,6 +469,17 @@ int main(int argc, char **argv)
                                 exit(save_errno);
                         }
                         break;
+               case 'n':
+                       oldpath = POP_ARG();
+                       if (oldpath == NULL)
+                               oldpath = fname;
+
+                       if (rename(oldpath, fname) < 0) {
+                               save_errno = errno;
+                               perror("rename()");
+                               exit(save_errno);
+                       }
+                       break;
                 case 'N':
                         newfile = POP_ARG();
                         if (!newfile)
@@ -378,12 +516,15 @@ int main(int argc, char **argv)
                        if (len <= 0)
                                len = 1;
                        if (bufsize < len) {
-                               buf = realloc(buf, len + ALIGN_LEN);
-                               if (buf == NULL) {
+                               void *tmp;
+                               tmp = realloc(buf, len + ALIGN_LEN);
+                               if (tmp == NULL) {
+                                       free(buf);
                                        save_errno = errno;
                                        perror("allocating buf for read\n");
                                        exit(save_errno);
                                }
+                               buf = tmp;
                                bufsize = len;
                                buf_align = (char *)((long)(buf + ALIGN_LEN) &
                                                     ~ALIGN_LEN);
@@ -471,12 +612,15 @@ int main(int argc, char **argv)
                        if (len <= 0)
                                len = 1;
                        if (bufsize < len) {
-                               buf = realloc(buf, len + ALIGN_LEN);
-                               if (buf == NULL) {
+                               void *tmp;
+                               tmp = realloc(buf, len + ALIGN_LEN);
+                               if (tmp == NULL) {
+                                       free(buf);
                                        save_errno = errno;
                                        perror("allocating buf for write\n");
                                        exit(save_errno);
                                }
+                               buf = tmp;
                                bufsize = len;
                                buf_align = (char *)((long)(buf + ALIGN_LEN) &
                                                     ~ALIGN_LEN);
@@ -495,10 +639,19 @@ int main(int argc, char **argv)
                                len -= rc;
                        }
                        break;
-                case 'W':
-                        for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
-                                mmap_ptr[i] += junk++;
-                        break;
+               case 'W':
+                       for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
+                               mmap_ptr[i] += junk++;
+                       break;
+               case 'x':
+                       rc = llapi_get_data_version(fd, &dv, 0);
+                       if (rc) {
+                               fprintf(stderr, "cannot get file data version"
+                                       " %d\n", rc);
+                               exit(-rc);
+                       }
+                       printf("dataversion is %ju\n", (uintmax_t)dv);
+                       break;
                 case 'y':
                         if (fsync(fd) == -1) {
                                 save_errno = errno;
@@ -507,11 +660,12 @@ int main(int argc, char **argv)
                         }
                         break;
                 case 'Y':
-                        if (fdatasync(fd) == -1) {
-                                save_errno = errno;
-                                perror("fdatasync");
-                                exit(save_errno);
-                        }
+                       if (fdatasync(fd) == -1) {
+                               save_errno = errno;
+                               perror("fdatasync");
+                               exit(save_errno);
+                       }
+                       break;
                 case 'z':
                         len = atoi(commands+1);
                         if (lseek(fd, len, SEEK_SET) == -1) {
@@ -520,6 +674,7 @@ int main(int argc, char **argv)
                                 exit(save_errno);
                         }
                         break;
+               case '-':
                 case '0':
                 case '1':
                 case '2':