Whamcloud - gitweb
LU-12472 tests: update sanity-krb5.sh
[fs/lustre-release.git] / lustre / tests / mmap_sanity.c
index 6b77254..90a2edb 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
  */
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2012, Whamcloud, Inc.
+ * Copyright (c) 2012, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
  * Lustre is a trademark of Sun Microsystems, Inc.
  */
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <limits.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <fcntl.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <netdb.h>
+#include <getopt.h>
 #include <string.h>
-#include <sys/wait.h>
-#include <sys/time.h>
+#include <errno.h>
+
+#include <libcfs/util/param.h>
 
 char *dir = NULL, *dir2 = NULL;
 long page_size;
@@ -55,9 +52,11 @@ char mmap_sanity[256];
 
 static void usage(void)
 {
-        printf("Usage: mmap_sanity -d dir [-m dir2]\n");
-        printf("       dir      lustre mount point\n");
-        printf("       dir2     another mount point\n");
+        printf("Usage: mmap_sanity -d dir [-m dir2] [-e <test cases>]\n");
+        printf("       -d dir        lustre mount point\n");
+        printf("       -m dir2       another mount point\n");
+        printf("       -e testcases  skipped test cases, -e 1 -e 2 to exclude"
+                                    " test cases 1 and 2.\n");
         exit(127);
 }
 
@@ -437,62 +436,56 @@ out_close:
         return rc;
 }
 
-static int cancel_lru_locks(char *prefix)
+static int cancel_lru_locks(char *filter)
 {
-        char cmd[256], line[1024];
-        FILE *file;
-        pid_t child;
-        int len = 1024, rc = 0;
-
-        child = fork();
-        if (child < 0)
-                return -errno;
-        else if (child) {
-                int status;
-                rc = waitpid(child, &status, WNOHANG);
-                if (rc == child)
-                        rc = 0;
-                return rc;
-        }
-
-        if (prefix)
-                sprintf(cmd,
-                        "ls /proc/fs/lustre/ldlm/namespaces/*-%s-*/lru_size",
-                        prefix);
-        else
-                sprintf(cmd, "ls /proc/fs/lustre/ldlm/namespaces/*/lru_size");
-
-        file = popen(cmd, "r");
-        if (file == NULL) {
-                perror("popen()");
-                return -errno;
-        }
-
-        while (fgets(line, len, file)) {
-                FILE *f;
-
-                if (!strlen(line))
-                        continue;
-                /* trim newline character */
-                *(line + strlen(line) - 1) = '\0';
-                f = fopen(line, "w");
-                if (f == NULL) {
-                        perror("fopen()");
-                        rc = -errno;
-                        break;
-                }
-                rc = fwrite("clear", strlen("clear") + 1, 1, f);
-                if (rc < 1) {
-                        perror("fwrite()");
-                        rc = -errno;
-                        fclose(f);
-                        break;
-                }
-                fclose(f);
-        }
-
-        pclose(file);
-        _exit(rc);
+       glob_t paths;
+       pid_t child;
+       int rc, i;
+
+       child = fork();
+       if (child < 0)
+               return -errno;
+       else if (child) {
+               int status;
+
+               rc = waitpid(child, &status, WNOHANG);
+               if (rc == child)
+                       rc = 0;
+               return rc;
+       }
+
+       if (filter != NULL)
+               rc = cfs_get_param_paths(&paths,
+                                       "ldlm/namespaces/*-%s-*/lru_size",
+                                       filter);
+       else
+               rc = cfs_get_param_paths(&paths,
+                                       "ldlm/namespaces/*/lru_size");
+       if (rc != 0)
+               return -EINVAL;
+
+       for (i = 0; i < paths.gl_pathc; i++) {
+               FILE *f = fopen(paths.gl_pathv[i], "r");
+               if (f == NULL) {
+                       rc = -errno;
+                       fprintf(stderr, "cannot open '%s': %s\n",
+                               paths.gl_pathv[i], strerror(errno));
+                       break;
+               }
+
+               rc = fwrite("clear", strlen("clear") + 1, 1, f);
+               if (rc < 1) {
+                       rc = -errno;
+                       fprintf(stderr, "fwrite failed for '%s': %s\n",
+                               paths.gl_pathv[i], strerror(errno));
+                       fclose(f);
+                       break;
+               }
+               fclose(f);
+       }
+
+       cfs_free_param_data(&paths);
+       _exit(rc);
 }
 
 /* don't dead lock while read/write file to/from the buffer which
@@ -755,6 +748,56 @@ out:
         return rc;
 }
 
+static int mmap_tst9(char *mnt)
+{
+        char  fname[256];
+        char *buf = MAP_FAILED;
+        int fd = -1;
+        int rc = 0;
+
+       if (snprintf(fname, 256, "%s/mmap_tst9", mnt) >= 256) {
+               fprintf(stderr, "dir name too long\n");
+               rc = -ENAMETOOLONG;
+               goto out;
+       }
+       if (unlink(fname) == -1 && errno != ENOENT) {
+               perror("unlink");
+               rc = -errno;
+               goto out;
+       }
+       fd = open(fname, O_RDWR | O_CREAT, 0644);
+       if (fd == -1) {
+               perror("open");
+               rc = -errno;
+               goto out;
+        }
+       buf = mmap(NULL, page_size * 2,
+                  PROT_READ , MAP_PRIVATE, fd, (loff_t)(-10 * page_size));
+       if (buf == MAP_FAILED) {
+               perror("mmap");
+               rc = -errno;
+               goto out;
+       }
+       rc = write(STDOUT_FILENO, buf, 2 * page_size);
+       if (rc != -1) {
+               fprintf(stderr, "write succeded with %d instead of failing\n", rc);
+               rc = -EINVAL;
+               goto out;
+       } else if (errno != EFAULT) {
+               fprintf(stderr, "write failed with %d instead of EFAULT(%d)\n",
+                       errno, EFAULT);
+               rc = -errno;
+               goto out;
+       }
+       rc = 0;
+out:
+       if (buf != MAP_FAILED)
+               munmap(buf, page_size * 2);
+       if (fd != -1)
+               close(fd);
+       return rc;
+}
+
 static int remote_tst(int tc, char *mnt)
 {
         int rc = 0;
@@ -778,29 +821,81 @@ struct test_case {
         char    *desc;                  /* test description */
         int     (*test_fn)(char *mnt);  /* test function */
         int     node_cnt;               /* node count */
+        int     skipped;                /* skipped by caller */
 };
 
 struct test_case tests[] = {
-        { 1, "mmap test1: basic mmap operation", mmap_tst1, 1 },
-        { 2, "mmap test2: MAP_PRIVATE not write back", mmap_tst2, 1 },
-        { 3, "mmap test3: concurrent mmap ops on two nodes", mmap_tst3, 2 },
-        { 4, "mmap test4: c1 write to f1 from mmapped f2, "
-             "c2 write to f1 from mmapped f1", mmap_tst4, 2 },
-        { 5, "mmap test5: read/write file to/from the buffer "
-             "which mmapped to just this file", mmap_tst5, 1 },
-        { 6, "mmap test6: check mmap write/read content on two nodes",
-                mmap_tst6, 2 },
-        { 7, "mmap test7: file i/o with an unmapped buffer", mmap_tst7, 1},
-        { 8, "mmap test8: SIGBUS for beyond file size", mmap_tst8, 1},
-        { 0, NULL, 0, 0 }
+       {
+               .tc             = 1,
+               .desc           = "mmap test1: basic mmap operation",
+               .test_fn        = mmap_tst1,
+               .node_cnt       = 1
+       },
+       {
+               .tc             = 2,
+               .desc           = "mmap test2: MAP_PRIVATE not write back",
+               .test_fn        = mmap_tst2,
+               .node_cnt       = 1
+       },
+       {
+               .tc             = 3,
+               .desc           = "mmap test3: concurrent mmap ops on "
+                                 "two nodes",
+               .test_fn        = mmap_tst3,
+               .node_cnt       = 2
+       },
+       {
+               .tc             = 4,
+               .desc           = "mmap test4: c1 write to f1 from mmapped f2, "
+                                 "c2 write to f1 from mmapped f1",
+               .test_fn        = mmap_tst4,
+               .node_cnt       = 2
+       },
+       {
+               .tc             = 5,
+               .desc           = "mmap test5: read/write file to/from the "
+                                 "buffer which mmapped to just this file",
+               .test_fn        = mmap_tst5,
+               .node_cnt       = 1
+       },
+       {
+               .tc             = 6,
+               .desc           = "mmap test6: check mmap write/read content "
+                                 "on two nodes",
+               .test_fn        = mmap_tst6,
+               .node_cnt       = 2
+       },
+       {
+               .tc             = 7,
+               .desc           = "mmap test7: file i/o with an unmapped "
+                                 "buffer",
+               .test_fn        = mmap_tst7,
+               .node_cnt       = 1
+       },
+       {
+               .tc             = 8,
+               .desc           = "mmap test8: SIGBUS for beyond file size",
+               .test_fn        = mmap_tst8,
+               .node_cnt       = 1
+       },
+       {
+               .tc             = 9,
+               .desc           = "mmap test9: SIGBUS for negative file offset",
+               .test_fn        = mmap_tst9,
+               .node_cnt       = 1
+       },
+       {
+               .tc             = 0
+       }
 };
 
 int main(int argc, char **argv)
 {
         struct test_case *test;
+        int nr_cases = sizeof(tests)/sizeof(*test);
         int c, rc = 0;
 
-        while ((c = getopt(argc, argv, "d:m:")) != -1) {
+        while ((c = getopt(argc, argv, "d:m:e:")) != -1) {
                 switch (c) {
                 case 'd':
                         dir = optarg;
@@ -808,6 +903,15 @@ int main(int argc, char **argv)
                 case 'm':
                         dir2 = optarg;
                         break;
+                case 'e': {
+                        char *endptr = NULL;
+                        rc = strtol(optarg, &endptr, 10);
+                        if (endptr != NULL && *endptr != '\0')
+                                usage();
+                        if (rc > 0 && rc < nr_cases)
+                                tests[rc - 1].skipped = 1;
+                        break;
+                }
                 default:
                         usage();
                         break;
@@ -822,11 +926,12 @@ int main(int argc, char **argv)
                 return -EINVAL;
         }
 
+        rc = 0;
         for (test = tests; test->tc; test++) {
-                double duration;
-                char *rs;
+                double duration = 0.0;
+                char *rs = "SKIPPED";
 
-                if (test->node_cnt == 1 || dir2 != NULL) {
+                if (!test->skipped && (test->node_cnt == 1 || dir2 != NULL)) {
                         struct timeval start, end;
 
                         gettimeofday(&start, NULL);
@@ -836,10 +941,8 @@ int main(int argc, char **argv)
                         duration = (double)(end.tv_sec - start.tv_sec) +
                                 (double)(end.tv_usec - start.tv_usec) / 1000000;
                         rs = rc ? "FAIL" : "PASS";
-                } else {
-                        duration = 0.0;
-                        rs = "SKIP";
                 }
+
                 fprintf(stderr, "%s (%s, %.5gs)\n", test->desc, rs, duration);
                 if (rc)
                         break;