Whamcloud - gitweb
LU-11388 test: disable replay-single test_131b
[fs/lustre-release.git] / lustre / tests / multiop.c
index 541e1b0..6f4169c 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * GPL HEADER END
  */
@@ -27,7 +23,7 @@
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2012, 2013, Intel Corporation.
+ * Copyright (c) 2012, 2017, 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 <malloc.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 <sys/file.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>
 
 #define T1 "write data before unlink\n"
@@ -62,17 +62,23 @@ 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 [path...]\n"
 "    command-sequence items:\n"
+"       A  fsetxattr(\"user.multiop\")\n"
+"       a[num] fgetxattr(\"user.multiop\") [optional buffer size, default 0]\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"
+"       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"
@@ -84,6 +90,7 @@ char usage[] =
 "       N  rename filename to path\n"
 "       o  open(O_RDONLY)\n"
 "       O  open(O_CREAT|O_RDWR)\n"
+"       p  print return value of last command\n"
 "       r[num] read [optional length]\n"
 "       R  reference entire mmap-ed region\n"
 "       s  stat\n"
@@ -99,7 +106,8 @@ char usage[] =
 "       W  write entire mmap-ed region\n"
 "       y  fsync\n"
 "       Y  fdatasync\n"
-"       z[num] seek [optional position, default 0]\n"
+"       z[num] lseek(SEEK_SET) [optional offset, default 0]\n"
+"       Z[num] lseek(SEEK_CUR) [optional offset, default 0]\n"
 "       _  wait for signal\n";
 
 void usr1_handler(int unused)
@@ -146,6 +154,9 @@ struct flag_mapping {
 #ifdef O_DIRECT
        {"O_DIRECT", O_DIRECT},
 #endif
+#ifdef O_NOATIME
+       {"O_NOATIME", O_NOATIME},
+#endif
        {"O_LARGEFILE", O_LARGEFILE},
        {"O_DIRECTORY", O_DIRECTORY},
        {"O_NOFOLLOW", O_NOFOLLOW},
@@ -203,15 +214,18 @@ int main(int argc, char **argv)
        struct statfs            stfs;
        size_t                   mmap_len = 0, i;
        unsigned char           *mmap_ptr = NULL, junk = 0;
-       int                      rc, len, fd = -1;
+       int                      len, fd = -1;
        int                      flags;
        int                      save_errno;
        int                      verbose = 0;
        int                      gid = 0;
-       lustre_fid               fid;
+       struct lu_fid            fid;
        struct timespec          ts;
        struct lov_user_md_v3    lum;
-       __u64                    dv;
+       char *xattr_buf = NULL;
+       size_t xattr_buf_size = 0;
+       long long rc = 0;
+       long long last_rc;
 
         if (argc < 3) {
                 fprintf(stderr, usage, argv[0]);
@@ -227,6 +241,11 @@ int main(int argc, char **argv)
         fname = argv[1];
 
         for (commands = argv[2]; *commands; commands++) {
+               /* XXX Most commands return 0 or we exit so we only
+                * update rc where really needed. */
+               last_rc = rc;
+               rc = 0;
+
                 switch (*commands) {
                 case '_':
                         if (verbose) {
@@ -240,6 +259,33 @@ 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':
+                       len = atoi(commands + 1);
+                       if (xattr_buf_size < len) {
+                               xattr_buf = realloc(xattr_buf, len);
+                               if (xattr_buf == NULL) {
+                                       save_errno = errno;
+                                       perror("allocating xattr buffer\n");
+                                       exit(save_errno);
+                               }
+
+                               xattr_buf_size = len;
+                       }
+
+                       rc = fgetxattr(fd, XATTR, xattr_buf, len);
+                       if (rc < 0) {
+                               save_errno = errno;
+                               perror("fgetxattr");
+                               exit(save_errno);
+                       }
+                       break;
                 case 'c':
                         if (close(fd) == -1) {
                                 save_errno = errno;
@@ -269,6 +315,7 @@ int main(int argc, char **argv)
                                 perror("create stripe file");
                                 exit(save_errno);
                         }
+                       rc = fd;
                         break;
                 case 'd':
                         if (mkdir(fname, 0755) == -1) {
@@ -284,14 +331,71 @@ int main(int argc, char **argv)
                                 perror("open(O_DIRECTORY)");
                                 exit(save_errno);
                         }
+                       rc = fd;
                         break;
-                case 'f':
-                        if (statfs(fname, &stfs) == -1) {
-                                save_errno = errno;
-                                perror("statfs()");
-                                exit(save_errno);
-                        }
-                        break;
+               case 'e':
+                       commands++;
+                       switch (*commands) {
+                       case 'U':
+                               rc = llapi_lease_release(fd);
+                               break;
+                       case 'R':
+                               rc = llapi_lease_acquire(fd, LL_LEASE_RDLCK);
+                               break;
+                       case 'W':
+                               rc = llapi_lease_acquire(fd, LL_LEASE_WRLCK);
+                               break;
+                       default:
+                               errx(-1, "unknown mode: %c", *commands);
+                       }
+                       if (rc < 0)
+                               err(errno, "apply/unlock 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(%lld) 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 = llapi_lease_check(fd);
+                       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(%lld) 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);
@@ -299,7 +403,7 @@ int main(int argc, char **argv)
                                rc = llapi_fd2fid(fd, &fid);
                        if (rc != 0)
                                fprintf(stderr,
-                                       "llapi_path/fd2fid() on %d, rc=%d\n",
+                                       "llapi_path/fd2fid() on %d, rc=%lld\n",
                                        fd, rc);
                        else
                                printf(DFID"\n", PFID(&fid));
@@ -330,6 +434,11 @@ int main(int argc, char **argv)
                                perror("create stripe file");
                                exit(save_errno);
                        }
+                       rc = fd;
+                       break;
+               case 'j':
+                       if (flock(fd, LOCK_EX) == -1)
+                               errx(-1, "flock()");
                        break;
                case 'K':
                        oldpath = POP_ARG();
@@ -413,6 +522,7 @@ int main(int argc, char **argv)
                                 perror("open(O_RDWR|O_CREAT)");
                                 exit(save_errno);
                         }
+                       rc = fd;
                         break;
                 case 'o':
                         len = get_flags(commands+1, &flags);
@@ -426,18 +536,25 @@ int main(int argc, char **argv)
                                 perror("open");
                                 exit(save_errno);
                         }
+                       rc = fd;
                         break;
+               case 'p':
+                       printf("%lld\n", last_rc);
+                       break;
                case 'r':
                        len = atoi(commands+1);
                        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);
@@ -450,14 +567,14 @@ int main(int argc, char **argv)
                                        exit(save_errno);
                                }
                                if (rc < len) {
-                                       fprintf(stderr, "short read: %u/%u\n",
+                                       fprintf(stderr, "short read: %lld/%u\n",
                                                rc, len);
                                        if (rc == 0)
                                                exit(ENODATA);
                                }
                                len -= rc;
                                if (verbose >= 2)
-                                       printf("%.*s\n", rc, buf_align);
+                                       printf("%.*s\n", (int)rc, buf_align);
                        }
                        break;
                 case 'R':
@@ -519,18 +636,22 @@ int main(int argc, char **argv)
                                perror("llapi_create_volatile");
                                exit(fd);
                        }
+                       rc = fd;
                        break;
                case 'w':
                        len = atoi(commands+1);
                        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);
@@ -544,7 +665,7 @@ int main(int argc, char **argv)
                                        exit(save_errno);
                                }
                                if (rc < len)
-                                       fprintf(stderr, "short write: %u/%u\n",
+                                       fprintf(stderr, "short write: %lld/%u\n",
                                                rc, len);
                                len -= rc;
                        }
@@ -553,15 +674,30 @@ int main(int argc, char **argv)
                        for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
                                mmap_ptr[i] += junk++;
                        break;
-               case 'x':
+               case 'x': {
+                       __u64 dv;
+
                        rc = llapi_get_data_version(fd, &dv, 0);
                        if (rc) {
                                fprintf(stderr, "cannot get file data version"
-                                       " %d\n", rc);
+                                       " %lld\n", rc);
+                               exit(-rc);
+                       }
+                       printf("dataversion is %ju\n", (uintmax_t)dv);
+                       break;
+               }
+               case 'X': {
+                       __u32 layout_version;
+
+                       rc = llapi_get_ost_layout_version(fd, &layout_version);
+                       if (rc) {
+                               fprintf(stderr, "cannot get ost layout version"
+                                       " %lld\n", rc);
                                exit(-rc);
                        }
-                       printf("dataversion is "LPU64"\n", dv);
+                       printf("ostlayoutversion: %u\n", layout_version);
                        break;
+               }
                 case 'y':
                         if (fsync(fd) == -1) {
                                 save_errno = errno;
@@ -570,19 +706,40 @@ int main(int argc, char **argv)
                         }
                         break;
                 case 'Y':
-                        if (fdatasync(fd) == -1) {
-                                save_errno = errno;
-                                perror("fdatasync");
-                                exit(save_errno);
-                        }
-                case 'z':
-                        len = atoi(commands+1);
-                        if (lseek(fd, len, SEEK_SET) == -1) {
-                                save_errno = errno;
-                                perror("lseek");
-                                exit(save_errno);
-                        }
-                        break;
+                       if (fdatasync(fd) == -1) {
+                               save_errno = errno;
+                               perror("fdatasync");
+                               exit(save_errno);
+                       }
+                       break;
+               case 'z': {
+                       off_t off;
+
+                       len = atoi(commands + 1);
+                       off = lseek(fd, len, SEEK_SET);
+                       if (off == (off_t)-1) {
+                               save_errno = errno;
+                               perror("lseek");
+                               exit(save_errno);
+                       }
+
+                       rc = off;
+                       break;
+               }
+               case 'Z': {
+                       off_t off;
+
+                       len = atoi(commands + 1);
+                       off = lseek(fd, len, SEEK_CUR);
+                       if (off == (off_t)-1) {
+                               save_errno = errno;
+                               perror("lseek");
+                               exit(save_errno);
+                       }
+
+                       rc = off;
+                       break;
+               }
                case '-':
                 case '0':
                 case '1':