Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / tests / multiop.c
index 776eaea..765c00b 100755 (executable)
@@ -1,7 +1,9 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  */
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE /* pull in O_DIRECTORY in bits/fcntl.h */
+#endif
 #include <stdio.h>
 #include <fcntl.h>
 #include <string.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <lustre/liblustreapi.h>
 
 #define T1 "write data before unlink\n"
 #define T2 "write data after unlink\n"
-char buf[128];
+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";
+char *buf, *buf_align;
+int bufsize = 0;
+#define ALIGN 65535
 
 char usage[] = 
 "Usage: %s filename command-sequence\n"
 "    command-sequence items:\n"
+"        c  close\n"
+"        C[num] create with optional stripes\n"
 "        d  mkdir\n"
 "        D  open(O_DIRECTORY)\n"
-"        o  open(O_RDONLY)\n"
-"        O  open(O_CREAT|O_RDWR)\n"
 "        L  link\n"
 "        l  symlink\n"
-"        u  unlink\n"
-"        U  munmap\n"
 "        m  mknod\n"
 "        M  rw mmap to EOF (must open and stat prior)\n"
 "        N  rename\n"
-"        c  close\n"
-"        _  wait for signal\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"
-"        r  read\n"
 "        s  stat\n"
 "        S  fstat\n"
 "        t  fchmod\n"
-"        T  ftruncate to zero\n"
-"        w  write\n"
+"        T[num] ftruncate [optional position, default 0]\n"
+"        u  unlink\n"
+"        U  munmap\n"
+"        w[num] write optional length\n"
 "        W  write entire mmap-ed region\n"
 "        y  fsync\n"
 "        Y  fdatasync\n"
-"        z  seek to zero\n";
+"        z[num] seek [optional position, default 0]\n"
+"        _  wait for signal\n";
 
-void null_handler(int unused) { }
+static int usr1_received;
+void usr1_handler(int unused)
+{
+        usr1_received = 1;
+}
 
 static const char *
 pop_arg(int argc, char *argv[])
@@ -57,7 +68,72 @@ pop_arg(int argc, char *argv[])
 
         return argv[cur_arg++];
 }
+
+struct flag_mapping {
+       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},
+#ifdef O_DIRECT
+       {"O_DIRECT", O_DIRECT},
+#endif
+       {"O_LARGEFILE", O_LARGEFILE},
+       {"O_DIRECTORY", O_DIRECTORY},
+       {"O_NOFOLLOW", O_NOFOLLOW},
+       {"", -1}
+};
+
+int get_flags(char *data, int *rflags)
+{
+        char *cloned_flags;
+        char *tmp;
+        int flag_set = 0;
+        int flags = 0;
+        int size = 0;
+
+        cloned_flags = strdup(data);
+        if (cloned_flags == NULL) {
+                fprintf(stderr, "Insufficient memory.\n");
+                exit(-1);
+        }
+
+        for (tmp = strtok(cloned_flags, ":"); tmp;
+             tmp = strtok(NULL, ":")) {
+                int i;
+
+                size = tmp - cloned_flags;
+                for (i = 0; flag_table[i].flag != -1; i++) {
+                        if (!strcmp(tmp, flag_table[i].string)){
+                                flags |= flag_table[i].flag;
+                                size += strlen(flag_table[i].string);
+                                flag_set = 1;
+                                break;
+                        }
+                }
+        }
+        free(cloned_flags);
+
+        if (!flag_set) {
+                *rflags = O_RDONLY;
+                return 0;
+        }
+
+        *rflags = flags;
+        return size;
+}
+
 #define POP_ARG() (pop_arg(argc, argv))
+#define min(a,b) ((a)>(b)?(b):(a))
 
 int main(int argc, char **argv)
 {
@@ -66,40 +142,58 @@ int main(int argc, char **argv)
         struct stat st;
         size_t mmap_len = 0, i;
         unsigned char *mmap_ptr = NULL, junk = 0;
-        int fd = -1;
+        int rc, len, fd = -1;
+        int flags;
+        int save_errno;
 
         if (argc < 3) {
                 fprintf(stderr, usage, argv[0]);
                 exit(1);
         }
 
-        signal(SIGUSR1, null_handler);
+        signal(SIGUSR1, usr1_handler);
 
         fname = argv[1];
 
         for (commands = argv[2]; *commands; commands++) {
                 switch (*commands) {
                 case '_':
-                        pause();
+                        if (usr1_received == 0)
+                                pause();
+                        usr1_received = 0;
+                        signal(SIGUSR1, usr1_handler);
                         break;
                 case 'c':
                         if (close(fd) == -1) {
+                                save_errno = errno;
                                 perror("close");
-                                exit(1);
+                                exit(save_errno);
                         }
                         fd = -1;
                         break;
+                case 'C':
+                        len = atoi(commands+1);
+                        fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
+                                             0, 0, len, 0);
+                        if (fd == -1) {
+                                save_errno = errno;
+                                perror("create stripe file");
+                                exit(save_errno);
+                        }
+                        break;
                 case 'd':
                         if (mkdir(fname, 0755) == -1) {
+                                save_errno = errno;
                                 perror("mkdir(0755)");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
                 case 'D':
                         fd = open(fname, O_DIRECTORY);
                         if (fd == -1) {
+                                save_errno = errno;
                                 perror("open(O_DIRECTORY)");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
                 case 'l':
@@ -107,8 +201,9 @@ int main(int argc, char **argv)
                         if (!newfile)
                                 newfile = fname;
                         if (symlink(fname, newfile)) {
+                                save_errno = errno;
                                 perror("symlink()");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
                 case 'L':
@@ -116,14 +211,16 @@ int main(int argc, char **argv)
                         if (!newfile)
                                 newfile = fname;
                         if (link(fname, newfile)) {
+                                save_errno = errno;
                                 perror("symlink()");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
                 case 'm':
                         if (mknod(fname, S_IFREG | 0644, 0) == -1) {
+                                save_errno = errno;
                                 perror("mknod(S_IFREG|0644, 0)");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
                 case 'M':
@@ -131,8 +228,9 @@ int main(int argc, char **argv)
                         mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
                                         MAP_SHARED, fd, 0);
                         if (mmap_ptr == MAP_FAILED) {
+                                save_errno = errno;
                                 perror("mmap");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
                 case 'N':
@@ -140,35 +238,55 @@ int main(int argc, char **argv)
                         if (!newfile)
                                 newfile = fname;
                         if (rename (fname, newfile)) {
+                                save_errno = errno;
                                 perror("rename()");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
                 case 'O':
                         fd = open(fname, O_CREAT|O_RDWR, 0644);
                         if (fd == -1) {
+                                save_errno = errno;
                                 perror("open(O_RDWR|O_CREAT)");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
                 case 'o':
-                        fd = open(fname, O_RDONLY);
+                        len = get_flags(commands+1, &flags);
+                        commands += len;
+                        fd = open(fname, flags);
                         if (fd == -1) {
-                                perror("open(O_RDONLY)");
-                                exit(1);
+                                save_errno = errno;
+                                perror("open");
+                                exit(save_errno);
                         }
                         break;
-                case 'r': {
-                        char buf;
-                        if (read(fd, &buf, 1) == -1) {
-                                perror("read");
-                                exit(1);
+                case 'r':
+                        len = atoi(commands+1);
+                        if (len <= 0)
+                                len = 1;
+                        if (bufsize < len) {
+                                buf = realloc(buf, len + ALIGN);
+                                if (buf == NULL) {
+                                        save_errno = errno;
+                                        perror("allocating buf for read\n");
+                                        exit(save_errno);
+                                }
+                                bufsize = len;
+                                buf_align = (char *)((long)(buf + ALIGN) &
+                                                     ~ALIGN);
                         }
-                        }
-                case 'S':
-                        if (fstat(fd, &st) == -1) {
-                                perror("fstat");
-                                exit(1);
+                        while (len > 0) {
+                                rc = read(fd, buf_align, len);
+                                if (rc == -1) {
+                                        save_errno = errno;
+                                        perror("read");
+                                        exit(save_errno);
+                                }
+                                if (rc < len)
+                                        fprintf(stderr, "short read: %u/%u\n",
+                                                rc, len);
+                                len -= rc;
                         }
                         break;
                 case 'R':
@@ -177,63 +295,113 @@ int main(int argc, char **argv)
                         break;
                 case 's':
                         if (stat(fname, &st) == -1) {
+                                save_errno = errno;
                                 perror("stat");
-                                exit(1);
+                                exit(save_errno);
+                        }
+                        break;
+                case 'S':
+                        if (fstat(fd, &st) == -1) {
+                                save_errno = errno;
+                                perror("fstat");
+                                exit(save_errno);
                         }
                         break;
                 case 't':
                         if (fchmod(fd, 0) == -1) {
+                                save_errno = errno;
                                 perror("fchmod");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
                 case 'T':
-                        if (ftruncate(fd, 0) == -1) {
+                        len = atoi(commands+1);
+                        if (ftruncate(fd, len) == -1) {
+                                save_errno = errno;
+                                printf("ftruncate (%d,%d)\n", fd, len);
                                 perror("ftruncate");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
                 case 'u':
                         if (unlink(fname) == -1) {
+                                save_errno = errno;
                                 perror("unlink");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
                 case 'U':
                         if (munmap(mmap_ptr, mmap_len)) {
+                                save_errno = errno;
                                 perror("munmap");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
-                case 'w': {
-                        int rc;
-                        if ((rc = write(fd, "w", 1)) == -1) {
-                                perror("write");
-                                exit(1);
+                case 'w':
+                        len = atoi(commands+1);
+                        if (len <= 0)
+                                len = 1;
+                        if (bufsize < len) {
+                                buf = realloc(buf, len + ALIGN);
+                                if (buf == NULL) {
+                                        save_errno = errno;
+                                        perror("allocating buf for write\n");
+                                        exit(save_errno);
+                                }
+                                bufsize = len;
+                                buf_align = (char *)((long)(buf + ALIGN) &
+                                                     ~ALIGN);
+                                strncpy(buf_align, msg, bufsize);
+                        }
+                        while (len > 0) {
+                                rc = write(fd, buf_align, len);
+                                if (rc == -1) {
+                                        save_errno = errno;
+                                        perror("write");
+                                        exit(save_errno);
+                                }
+                                if (rc < len)
+                                        fprintf(stderr, "short write: %u/%u\n",
+                                                rc, len);
+                                len -= rc;
                         }
                         break;
-                }
                 case 'W':
                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
                                 mmap_ptr[i] += junk++;
                         break;
                 case 'y':
                         if (fsync(fd) == -1) {
+                                save_errno = errno;
                                 perror("fsync");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
                 case 'Y':
                         if (fdatasync(fd) == -1) {
+                                save_errno = errno;
                                 perror("fdatasync");
-                                exit(1);
+                                exit(save_errno);
                         }
                 case 'z':
-                        if (lseek(fd, 0, SEEK_SET) == -1) {
+                        len = atoi(commands+1);
+                        if (lseek(fd, len, SEEK_SET) == -1) {
+                                save_errno = errno;
                                 perror("lseek");
-                                exit(1);
+                                exit(save_errno);
                         }
                         break;
+                case '0':
+                case '1':
+                case '2':
+                case '3':
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                case '8':
+                case '9':
+                        break;
                 default:
                         fprintf(stderr, "unknown command \"%c\"\n", *commands);
                         fprintf(stderr, usage, argv[0]);
@@ -241,5 +409,8 @@ int main(int argc, char **argv)
                 }
         }
 
+        if (buf)
+                free(buf);
+
         return 0;
 }