Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / liblustre / tests / sanity.c
index fce471c..e46f480 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #define _BSD_SOURCE
+#define _FILE_OFFSET_BITS 64
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <dirent.h>
 #include <sys/uio.h>
 #include <sys/time.h>
+#include <time.h>
+#include <sys/ioctl.h>
 
 #include "test_common.h"
+#include <ioctl.h>
+#include <lustre/liblustreapi.h>
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE getpagesize()
+#endif
+#define _npages (2048)
+
+void *buf_alloc;
+int buf_size;
+int opt_verbose;
+struct timeval start;
 
 extern char *lustre_path;
 
@@ -46,7 +61,7 @@ extern char *lustre_path;
         do {                                                            \
                 char buf[100];                                          \
                 int len;                                                \
-                sprintf(buf, "===== START: %s ", (str));                \
+                sprintf(buf, "===== START %s: %s ", __FUNCTION__, (str)); \
                 len = strlen(buf);                                      \
                 if (len < 79) {                                         \
                         memset(buf+len, '=', 100-len);                  \
@@ -54,30 +69,47 @@ extern char *lustre_path;
                         buf[80] = 0;                                    \
                 }                                                       \
                 printf("%s", buf);                                      \
+                gettimeofday(&start, NULL);                             \
         } while (0)
 
 #define LEAVE()                                                         \
         do {                                                            \
-                printf("----- END TEST successfully ---");              \
-                printf("-----------------------------");                \
-                printf("-------------------\n");                        \
+                struct timeval stop;                                    \
+                char buf[100] = { '\0' };                               \
+                int len = sizeof(buf) - 1;                              \
+                long usec;                                              \
+                gettimeofday(&stop, NULL);                              \
+                usec = (stop.tv_sec - start.tv_sec) * 1000000 +         \
+                       (stop.tv_usec - start.tv_usec);                  \
+                len = snprintf(buf, len,                                \
+                               "===== END TEST %s: successfully (%gs)", \
+                               __FUNCTION__, (double)usec / 1000000);   \
+                if (len < 79) {                                         \
+                        memset(buf+len, '=', sizeof(buf) - len);        \
+                        buf[79] = '\n';                                 \
+                        buf[80] = 0;                                    \
+                }                                                       \
+                printf("%s", buf);                                      \
+                return 0;                                               \
         } while (0)
 
 #define MAX_PATH_LENGTH 4096
 
-void t1()
+int t1(char *name)
 {
         char path[MAX_PATH_LENGTH] = "";
 
-        ENTRY("create/delete");
         snprintf(path, MAX_PATH_LENGTH, "%s/test_t1", lustre_path);
 
+        if (opt_verbose)
+                printf("touch+unlink %s\n", path);
+
         t_touch(path);
         t_unlink(path);
         LEAVE();
 }
 
-void t2()
+int t2(char *name)
 {
         char path[MAX_PATH_LENGTH] = "";
 
@@ -89,7 +121,7 @@ void t2()
         LEAVE();
 }
 
-void t3()
+int t3(char *name)
 {
         char path[MAX_PATH_LENGTH] = "";
 
@@ -102,7 +134,7 @@ void t3()
         LEAVE();
 }
 
-void t4()
+int t4(char *name)
 {
         char path[MAX_PATH_LENGTH] = "";
 
@@ -115,7 +147,7 @@ void t4()
         LEAVE();
 }
 
-void t6()
+int t6(char *name)
 {
         char path[MAX_PATH_LENGTH] = "";
         char path2[MAX_PATH_LENGTH] = "";
@@ -132,7 +164,42 @@ void t6()
         LEAVE();
 }
 
-void t7()
+int t6b(char *name)
+{
+        char path[MAX_PATH_LENGTH] = "";
+        char path2[MAX_PATH_LENGTH] = "";
+        char cwd[MAX_PATH_LENGTH] = "";
+        char *tmp;
+        int fd;
+
+        ENTRY("symlink + chdir and open");
+        snprintf(path, MAX_PATH_LENGTH, "%s/test_t6b", lustre_path);
+        snprintf(path2, MAX_PATH_LENGTH, "%s/test_t6b_link", lustre_path);
+
+        t_mkdir(path);
+        t_symlink(path, path2);
+        t_check_stat(path2, NULL);
+
+        tmp = getcwd(cwd, MAX_PATH_LENGTH);
+        if (tmp == NULL) {
+                fprintf(stderr, "current path too long to fit in "
+                        "MAX_PATH_LENGTH?\n");
+                LEAVE();
+        }
+        t_chdir(path2);
+        t_chdir(cwd);
+        t_rmdir(path);
+        t_touch(path);
+
+        fd = t_open(path2);
+        t_close(fd);
+
+        t_unlink(path2);
+        t_unlink(path);
+        LEAVE();
+}
+
+int t7(char *name)
 {
         char path[MAX_PATH_LENGTH] = "";
         int rc;
@@ -154,21 +221,29 @@ void t7()
         LEAVE();
 }
 
-void t8()
+int t8(char *name)
 {
         char path[MAX_PATH_LENGTH] = "";
 
         ENTRY("chmod");
         snprintf(path, MAX_PATH_LENGTH, "%s/test_t8", lustre_path);
 
+        /* Check file. */
         t_touch(path);
         t_chmod_raw(path, 0700);
         t_check_stat(path, NULL);
         t_unlink(path);
+
+        /* Check dir. */
+        t_mkdir(path);
+        t_chmod_raw(path, 0700);
+        t_check_stat(path, NULL);
+        t_rmdir(path);
+
         LEAVE();
 }
 
-void t9()
+int t9(char *name)
 {
         char path[MAX_PATH_LENGTH] = "";
         char path2[MAX_PATH_LENGTH] = "";
@@ -186,7 +261,7 @@ void t9()
         LEAVE();
 }
 
-void t10()
+int t10(char *name)
 {
         char dir1[MAX_PATH_LENGTH] = "";
         char dir2[MAX_PATH_LENGTH] = "";
@@ -219,7 +294,7 @@ void t10()
         LEAVE();
 }
 
-void t11()
+int t11(char *name)
 {
         char *base=lustre_path;
         char path[MAX_PATH_LENGTH], path2[MAX_PATH_LENGTH];
@@ -242,7 +317,7 @@ void t11()
                 safe_strncpy(path, base, MAX_PATH_LENGTH);
                 for (j = 1; j < i; j++)
                         strcat(path, "/dir");
-                
+
                 for (j = 0; j < nreg; j++) {
                         sprintf(path2, "%s/file%d", path, j);
                         t_unlink(path2);
@@ -255,7 +330,7 @@ void t11()
         LEAVE();
 }
 
-void t12()
+int t12(char *name)
 {
         char dir[MAX_PATH_LENGTH] = "";
         char buf[1024*128];
@@ -271,10 +346,10 @@ void t12()
         LEAVE();
 }
 
-void t13()
+int t13(char *name)
 {
         char dir[MAX_PATH_LENGTH] = "";
-        char name[1024];
+        char path[1024];
         char buf[1024];
         const int nfiles = 20;
         char *prefix = "test13_filename_prefix_";
@@ -285,81 +360,85 @@ void t13()
         t_mkdir(dir);
         printf("Creating %d files...\n", nfiles);
         for (i = 0; i < nfiles; i++) {
-                sprintf(name, "%s%s%05d", dir, prefix, i);
-                t_touch(name);
+                sprintf(path, "%s%s%05d", dir, prefix, i);
+                t_touch(path);
         }
         fd = t_opendir(dir);
         t_ls(fd, buf, sizeof(buf));
         t_close(fd);
         printf("Cleanup...\n");
         for (i = 0; i < nfiles; i++) {
-                sprintf(name, "%s%s%05d", dir, prefix, i);
-                t_unlink(name);
+                sprintf(path, "%s%s%05d", dir, prefix, i);
+                t_unlink(path);
         }
         t_rmdir(dir);
         LEAVE();
 }
 
-void t14()
+int t14(char *name)
 {
         char dir[MAX_PATH_LENGTH] = "";
-        char name[1024];
+        char path[1024];
         char buf[1024];
         const int nfiles = 256;
         char *prefix = "test14_filename_long_prefix_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA___";
-       struct dirent64 *ent;
+        struct dirent64 *ent;
         int fd, i, rc, pos, index;
-       loff_t base = 0;
+        loff_t base = 0;
         ENTRY(">1 block(4k) directory readdir");
         snprintf(dir, MAX_PATH_LENGTH, "%s/test_t14_dir/", lustre_path);
 
-        t_mkdir(dir);
+        rc = mkdir(dir, 0755);
+        if (rc < 0 && errno != EEXIST) {
+                printf("mkdir(%s) error: %s\n", dir, strerror(errno));
+                exit(1);
+        }
         printf("Creating %d files...\n", nfiles);
         for (i = 0; i < nfiles; i++) {
-                sprintf(name, "%s%s%05d", dir, prefix, i);
-                t_touch(name);
+                sprintf(path, "%s%s%05d", dir, prefix, i);
+                t_touch(path);
         }
         fd = t_opendir(dir);
         printf("Listing...\n");
         index = 0;
-       while ((rc = getdirentries64(fd, buf, 1024, &base)) > 0) {
-               pos = 0;
-               while (pos < rc) {
+        while ((rc = getdirentries64(fd, buf, 1024, &base)) > 0) {
+                pos = 0;
+                while (pos < rc) {
                         char *item;
 
-                       ent = (struct dirent64 *) ((char*) buf + pos);
+                        ent = (struct dirent64 *) ((char*) buf + pos);
                         item = (char *) ent->d_name;
                         if (!strcmp(item, ".") || !strcmp(item, ".."))
                                 goto iter;
                         if (strstr(item, prefix) != item) {
                                 printf("found bad name %s\n", item);
-                                exit(-1);
+                                return(-1);
                         }
-                       printf("[%03d]: %s\n",
+                        printf("[%03d]: %s\n",
                                 index++, item + strlen(prefix));
 iter:
-                       pos += ent->d_reclen;
-               }
-       }
-       if (rc < 0) {
-               printf("getdents error %d\n", rc);
-                exit(-1);
-       }
+                        pos += ent->d_reclen;
+                }
+        }
+        if (rc < 0) {
+                printf("getdents error %d\n", rc);
+                return(-1);
+        }
         if (index != nfiles) {
                 printf("get %d files != %d\n", index, nfiles);
-                exit(-1);
+                return(-1);
         }
         t_close(fd);
         printf("Cleanup...\n");
         for (i = 0; i < nfiles; i++) {
-                sprintf(name, "%s%s%05d", dir, prefix, i);
-                t_unlink(name);
+                sprintf(path, "%s%s%05d", dir, prefix, i);
+                t_unlink(path);
         }
         t_rmdir(dir);
         LEAVE();
 }
 
-void t15()
+int t15(char *name)
 {
         char file[MAX_PATH_LENGTH] = "";
         int fd;
@@ -374,7 +453,7 @@ void t15()
         LEAVE();
 }
 
-void t16()
+int t16(char *name)
 {
         char file[MAX_PATH_LENGTH] = "";
         ENTRY("small-write-read");
@@ -386,7 +465,7 @@ void t16()
         LEAVE();
 }
 
-void t17()
+int t17(char *name)
 {
         char file[MAX_PATH_LENGTH] = "";
         int fd;
@@ -396,58 +475,106 @@ void t17()
         fd = open(file, O_WRONLY | O_CREAT, 0666);
         if (fd < 0) {
                 printf("failed to create file: %s\n", strerror(errno));
-                exit(-1);
+                return(-1);
         }
         t_unlink(file);
         LEAVE();
 }
 
-void t18()
+int t18(char *name)
 {
         char file[MAX_PATH_LENGTH] = "";
         char buf[128];
         int fd, i;
         struct stat statbuf[3];
-        ENTRY("write should change mtime/atime");
+        ENTRY("write should change mtime/ctime");
         snprintf(file, MAX_PATH_LENGTH, "%s/test_t18_file", lustre_path);
 
         for (i = 0; i < 3; i++) {
                 fd = open(file, O_RDWR|O_CREAT|O_APPEND, (mode_t)0666);
                 if (fd < 0) {
                         printf("error open file: %s\n", strerror(errno));
-                        exit(-1);
+                        return(-1);
                 }
                 if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
                         printf("error write file\n");
-                        exit(-1);
+                        return(-1);
                 }
                 close(fd);
                 if(stat(file, &statbuf[i]) != 0) {
                         printf("Error stat\n");
-                        exit(1);
+                        return(1);
                 }
-                printf("mtime %lu, ctime %lu\n",
-                        statbuf[i].st_atime, statbuf[i].st_mtime);
+                printf("ctime %lu, mtime %lu\n",
+                        statbuf[i].st_ctime, statbuf[i].st_mtime);
                 sleep(2);
         }
 
         for (i = 1; i < 3; i++) {
-                if ((statbuf[i].st_atime <= statbuf[i-1].st_atime) ||
+                if ((statbuf[i].st_ctime <= statbuf[i-1].st_ctime) ||
                     (statbuf[i].st_mtime <= statbuf[i-1].st_mtime)) {
                         printf("time error\n");
-                        exit(-1);
+                        return(-1);
                 }
         }
         t_unlink(file);
         LEAVE();
 }
 
-void t19()
+int t18b(char *name)
 {
         char file[MAX_PATH_LENGTH] = "";
-        int fd;
+        int i;
+        struct stat statbuf[3];
+        ENTRY("utime should change mtime/atime/ctime");
+        snprintf(file, MAX_PATH_LENGTH, "%s/test_t18b_file", lustre_path);
+        t_touch(file);
+
+        for (i = 0; i < 3; i++) {
+                t_utime(file, NULL);
+                if(stat(file, &statbuf[i]) != 0) {
+                        printf("Error stat\n");
+                        return(1);
+                }
+                printf("atime %lu, mtime %lu, ctime %lu\n",
+                       statbuf[i].st_atime, statbuf[i].st_mtime,
+                       statbuf[i].st_ctime);
+                sleep(2);
+        }
+
+        for (i = 1; i < 3; i++) {
+                if ((statbuf[i].st_atime <= statbuf[i-1].st_atime) ||
+                    (statbuf[i].st_mtime <= statbuf[i-1].st_mtime) ||
+                    (statbuf[i].st_ctime <= statbuf[i-1].st_ctime)) {
+                        printf("time error\n");
+                        return(-1);
+                }
+        }
+        t_unlink(file);
+        LEAVE();
+}
+
+static int check_file_size(char *file, off_t size)
+{
         struct stat statbuf;
-        ENTRY("open(O_TRUNC) should trancate file to 0-length");
+
+        if (stat(file, &statbuf) != 0) {
+                printf("Error stat(%s)\n", file);
+                return(1);
+        }
+        if (statbuf.st_size != size) {
+                printf("size of %s: %ld != %lld\n", file, statbuf.st_size, size);
+                return(-1);
+        }
+        return 0;
+}
+
+int t19(char *name)
+{
+        char file[MAX_PATH_LENGTH] = "";
+        int fd;
+        int result;
+        ENTRY("open(O_TRUNC) should truncate file to 0-length");
         snprintf(file, MAX_PATH_LENGTH, "%s/test_t19_file", lustre_path);
 
         t_echo_create(file, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
@@ -455,22 +582,17 @@ void t19()
         fd = open(file, O_RDWR|O_CREAT|O_TRUNC, (mode_t)0666);
         if (fd < 0) {
                 printf("error open file: %s\n", strerror(errno));
-                exit(-1);
+                return(-1);
         }
         close(fd);
-        if(stat(file, &statbuf) != 0) {
-                printf("Error stat\n");
-                exit(1);
-        }
-        if (statbuf.st_size != 0) {
-                printf("size %ld is not zero\n", statbuf.st_size);
-                exit(-1);
-        }
+        result = check_file_size(file, 0);
+        if (result != 0)
+                return result;
         t_unlink(file);
         LEAVE();
 }
 
-void t20()
+int t20(char *name)
 {
         char file[MAX_PATH_LENGTH] = "";
         int fd;
@@ -483,18 +605,18 @@ void t20()
         fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
         if (fd < 0) {
                 printf("error open file: %s\n", strerror(errno));
-                exit(-1);
+                return(-1);
         }
 
         ret = write(fd, NULL, 20);
         if (ret != -1 || errno != EFAULT) {
                 printf("write 1: ret %ld, errno %d\n", ret, errno);
-                exit(1);
+                return(1);
         }
         ret = write(fd, (void *)-1, 20);
         if (ret != -1 || errno != EFAULT) {
                 printf("write 2: ret %ld, errno %d\n", ret, errno);
-                exit(1);
+                return(1);
         }
         iov[0].iov_base = NULL;
         iov[0].iov_len = 10;
@@ -503,7 +625,7 @@ void t20()
         ret = writev(fd, iov, 2);
         if (ret != -1 || errno != EFAULT) {
                 printf("writev 1: ret %ld, errno %d\n", ret, errno);
-                exit(1);
+                return(1);
         }
         iov[0].iov_base = NULL;
         iov[0].iov_len = 0;
@@ -512,19 +634,19 @@ void t20()
         ret = writev(fd, iov, 2);
         if (ret != sizeof(buf)) {
                 printf("write 3 ret %ld, error %d\n", ret, errno);
-                exit(1);
+                return(1);
         }
         lseek(fd, 0, SEEK_SET);
 
         ret = read(fd, NULL, 20);
         if (ret != -1 || errno != EFAULT) {
                 printf("read 1: ret %ld, errno %d\n", ret, errno);
-                exit(1);
+                return(1);
         }
         ret = read(fd, (void *)-1, 20);
         if (ret != -1 || errno != EFAULT) {
                 printf("read 2: ret %ld, errno %d\n", ret, errno);
-                exit(1);
+                return(1);
         }
         iov[0].iov_base = NULL;
         iov[0].iov_len = 10;
@@ -533,7 +655,7 @@ void t20()
         ret = readv(fd, iov, 2);
         if (ret != -1 || errno != EFAULT) {
                 printf("readv 1: ret %ld, errno %d\n", ret, errno);
-                exit(1);
+                return(1);
         }
         iov[0].iov_base = NULL;
         iov[0].iov_len = 0;
@@ -542,7 +664,7 @@ void t20()
         ret = readv(fd, iov, 2);
         if (ret != sizeof(buf)) {
                 printf("read 3 ret %ld, error %d\n", ret, errno);
-                exit(1);
+                return(1);
         }
 
         close(fd);
@@ -550,33 +672,44 @@ void t20()
         LEAVE();
 }
 
-void t21()
+int t21(char *name)
 {
         char file[MAX_PATH_LENGTH] = "";
         int fd, ret;
+        struct flock lock = {
+                .l_type = F_RDLCK,
+                .l_whence = SEEK_SET,
+        };
+
         ENTRY("basic fcntl support");
         snprintf(file, MAX_PATH_LENGTH, "%s/test_t21_file", lustre_path);
 
         fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
         if (fd < 0) {
-                printf("error open file: %s\n", strerror(errno));
-                exit(-1);
+                printf("error open file: %s\n", file);
+                return(-1);
         }
-        if (fcntl(fd, F_SETFL, O_APPEND)) {
-                printf("error set flag: %s\n", strerror(errno));
-                exit(-1);
-        }
-        if ((ret = fcntl(fd, F_GETFL)) != O_APPEND) {
+
+        t_fcntl(fd, F_SETFL, O_APPEND);
+        if (!(ret = t_fcntl(fd, F_GETFL)) & O_APPEND) {
                 printf("error get flag: ret %x\n", ret);
-                exit(-1);
+                return(-1);
         }
 
+        t_fcntl(fd, F_SETLK, &lock);
+        t_fcntl(fd, F_GETLK, &lock);
+        lock.l_type = F_WRLCK;
+        t_fcntl(fd, F_SETLKW, &lock);
+        t_fcntl(fd, F_GETLK, &lock);
+        lock.l_type = F_UNLCK;
+        t_fcntl(fd, F_SETLK, &lock);
+
         close(fd);
         t_unlink(file);
         LEAVE();
 }
 
-void t22()
+int t22(char *name)
 {
         char file[MAX_PATH_LENGTH] = "";
         int fd;
@@ -589,50 +722,50 @@ void t22()
         fd = open(file, O_RDWR|O_CREAT|O_APPEND, (mode_t)0666);
         if (fd < 0) {
                 printf("error open file: %s\n", strerror(errno));
-                exit(-1);
+                return(-1);
         }
 
         lseek(fd, 100, SEEK_SET);
         ret = write(fd, str, strlen(str));
         if (ret != strlen(str)) {
                 printf("write 1: ret %ld, errno %d\n", ret, errno);
-                exit(1);
+                return(1);
         }
 
         lseek(fd, 0, SEEK_SET);
         ret = read(fd, buf, sizeof(buf));
         if (ret != strlen(str)) {
                 printf("read 1 got %ld\n", ret);
-                exit(1);
+                return(1);
         }
 
         if (memcmp(buf, str, strlen(str))) {
                 printf("read 1 data err\n");
-                exit(1);
+                return(1);
         }
 
         if (fcntl(fd, F_SETFL, 0)) {
                 printf("fcntl err: %s\n", strerror(errno));
-                exit(1);
+                return(1);
         }
 
         lseek(fd, 100, SEEK_SET);
         ret = write(fd, str, strlen(str));
         if (ret != strlen(str)) {
                 printf("write 2: ret %ld, errno %d\n", ret, errno);
-                exit(1);
+                return(1);
         }
 
         lseek(fd, 100, SEEK_SET);
         ret = read(fd, buf, sizeof(buf));
         if (ret != strlen(str)) {
                 printf("read 2 got %ld\n", ret);
-                exit(1);
+                return(1);
         }
 
         if (memcmp(buf, str, strlen(str))) {
                 printf("read 2 data err\n");
-                exit(1);
+                return(1);
         }
 
         close(fd);
@@ -640,85 +773,185 @@ void t22()
         LEAVE();
 }
 
+int t23(char *name)
+{
+        char path[MAX_PATH_LENGTH];
+        int fd;
+        long long ret;
+        loff_t off;
 
-#define PAGE_SIZE (4096)
-#define _npages (2048)
+        ENTRY("handle seek > 2GB");
+        snprintf(path, MAX_PATH_LENGTH, "%s/f%s", lustre_path, name);
+
+        fd = open(path, O_WRONLY | O_CREAT | O_LARGEFILE, 0666);
+        if (fd < 0) {
+                printf("failed to create file %s: %s\n", path, strerror(errno));
+                return(-1);
+        }
+
+        off = 2048ULL * 1024 * 1024 - buf_size / 2;
+        ret = lseek(fd, off, SEEK_SET);
+        if (ret != off) {
+                printf("seek error for initial %llu != %llu\n",
+                       ret, (long long)off);
+                return -1;
+        }
+
+        ret = write(fd, buf_alloc, buf_size);
+        if (ret != buf_size) {
+                printf("write error for %d != %llubytes @ %llu\n",
+                       buf_size, ret, (long long)off);
+                if (ret == -1)
+                        perror("write");
+                return -1;
+        }
+
+        ret = lseek(fd, off, SEEK_SET);
+        if (ret != off) {
+                printf("seek < 2GB error for %llu != %llu\n",
+                       ret, (long long)off);
+                if (ret == -1)
+                        perror("seek < 2GB");
+                return -1;
+        }
+
+        ret = lseek(fd, off + buf_size - 2, SEEK_SET);
+        if (ret != off + buf_size - 2) {
+                printf("seek > 2GB error for %llu != %llu\n",
+                       ret, (long long)off);
+                if (ret == -1)
+                        perror("seek > 2GB");
+                return -1;
+        }
+
+        ret = lseek(fd, -buf_size + 2, SEEK_CUR);
+        if (ret != off) {
+                printf("relative seek error for %d %llu != %llu\n",
+                       -buf_size + 2, ret, off);
+                if (ret == -1)
+                        perror("relative seek");
+                return -1;
+        }
 
-static int _buffer[_npages][PAGE_SIZE/sizeof(int)];
+        ret = lseek(fd, 0, SEEK_END);
+        if (ret != off + buf_size) {
+                printf("end seek error for %llu != %llu\n",
+                       ret, (long long)off + buf_size);
+                if (ret == -1)
+                        perror("end seek");
+                return -1;
+        }
+
+        ret = lseek(fd, 0, SEEK_SET);
+        if (ret != 0) {
+                printf("seek 0 error for %llu != 0\n", ret);
+                if (ret == -1)
+                        perror("seek 0");
+                return -1;
+        }
+
+        off = 2048ULL * 1024 * 1024, SEEK_SET;
+        ret = lseek(fd, off, SEEK_SET);
+        if (ret != off) {
+                printf("seek 2GB error for %llu != %llu\n", ret, off);
+                if (ret == -1)
+                        perror("seek 2GB");
+                return -1;
+        }
+
+        close(fd);
+        t_unlink(path);
+        LEAVE();
+}
 
 /* pos:   i/o start from
  * xfer:  npages per transfer
  */
-static void pages_io(int xfer, loff_t pos)
+static int pages_io(int xfer, loff_t pos)
 {
         char path[MAX_PATH_LENGTH] = "";
 
-        int check_sum[_npages] = {0,};
+        int check_sum[_npages] = {0,}, *buf;
         int fd, rc, i, j, data_error = 0;
         struct timeval tw1, tw2, tr1, tr2;
         double tw, tr;
+        loff_t ret;
 
         snprintf(path, MAX_PATH_LENGTH, "%s/test_t50", lustre_path);
-        memset(_buffer, 0, sizeof(_buffer));
+
+        memset(buf_alloc, 0, buf_size);
 
         /* create sample data */
-        for (i = 0; i < _npages; i++) {
-                for (j = 0; j < PAGE_SIZE/sizeof(int); j++) {
-                        _buffer[i][j] = rand();
+        for (i = 0, buf = buf_alloc; i < _npages; i++) {
+                for (j = 0; j < PAGE_SIZE/sizeof(int); j++, buf++) {
+                        *buf = rand();
                 }
         }
 
         /* compute checksum */
-        for (i = 0; i < _npages; i++) {
-                for (j = 0; j < PAGE_SIZE/sizeof(int); j++) {
-                        check_sum[i] += _buffer[i][j];
+        for (i = 0, buf = buf_alloc; i < _npages; i++) {
+                for (j = 0; j < PAGE_SIZE/sizeof(int); j++, buf++) {
+                        check_sum[i] += *buf;
                 }
         }
 
+        unlink(path);
         t_touch(path);
 
-       fd = t_open(path);
+        fd = t_open(path);
 
         /* write */
-       lseek(fd, pos, SEEK_SET);
+        ret = lseek(fd, pos, SEEK_SET);
+        if (ret != pos) {
+                perror("write seek");
+                return 1;
+        }
         gettimeofday(&tw1, NULL);
-       for (i = 0; i < _npages; i += xfer) {
-               rc = write(fd, _buffer[i], PAGE_SIZE * xfer);
+        for (i = 0, buf = buf_alloc; i < _npages;
+             i += xfer, buf += xfer * PAGE_SIZE / sizeof(int)) {
+                rc = write(fd, buf, PAGE_SIZE * xfer);
                 if (rc != PAGE_SIZE * xfer) {
-                        printf("write error %d (i = %d)\n", rc, i);
-                        exit(1);
+                        printf("write error (i %d, rc %d): %s\n", i, rc,
+                               strerror(errno));
+                        return(1);
                 }
-       }
+        }
         gettimeofday(&tw2, NULL);
 
-        memset(_buffer, 0, sizeof(_buffer));
+        memset(buf_alloc, 0, buf_size);
 
         /* read */
-       lseek(fd, pos, SEEK_SET);
+        ret = lseek(fd, pos, SEEK_SET);
+        if (ret != pos) {
+                perror("read seek");
+                return 1;
+        }
         gettimeofday(&tr1, NULL);
-       for (i = 0; i < _npages; i += xfer) {
-               rc = read(fd, _buffer[i], PAGE_SIZE * xfer);
+        for (i = 0, buf = buf_alloc; i < _npages;
+             i += xfer, buf += xfer * PAGE_SIZE / sizeof(int)) {
+                rc = read(fd, buf, PAGE_SIZE * xfer);
                 if (rc != PAGE_SIZE * xfer) {
-                        printf("read error %d (i = %d)\n", rc, i);
-                        exit(1);
+                        printf("read error (i %d, rc %d): %s\n", i, rc,
+                               strerror(errno));
+                        return(1);
                 }
-       }
+        }
         gettimeofday(&tr2, NULL);
 
         /* compute checksum */
-        for (i = 0; i < _npages; i++) {
+        for (i = 0, buf = buf_alloc; i < _npages; i++) {
                 int sum = 0;
-                for (j = 0; j < PAGE_SIZE/sizeof(int); j++) {
-                        sum += _buffer[i][j];
+                for (j = 0; j < PAGE_SIZE/sizeof(int); j++, buf++) {
+                        sum += *buf;
                 }
                 if (sum != check_sum[i]) {
                         data_error = 1;
-                        printf("chunk %d checksum error: expected 0x%x, get 0x%x\n",
+                        printf("chunk %d checksum error expected %#x got %#x\n",
                                 i, check_sum[i], sum);
                 }
         }
 
-       t_close(fd);
+        t_close(fd);
         t_unlink(path);
         tw = (tw2.tv_sec - tw1.tv_sec) * 1000000 + (tw2.tv_usec - tw1.tv_usec);
         tr = (tr2.tv_sec - tr1.tv_sec) * 1000000 + (tr2.tv_usec - tr1.tv_usec);
@@ -727,106 +960,562 @@ static void pages_io(int xfer, loff_t pos)
                 (_npages * PAGE_SIZE) / (tr / 1000000.0) / (1024 * 1024));
 
         if (data_error)
-                exit(1);
+                return 1;
+
+        return 0;
 }
 
-void t50()
+int t50(char *name)
 {
-        loff_t off_array[] = {1, 17, 255, 258, 4095, 4097, 8191,
-                              1024*1024*1024*1024ULL};
-        int np = 1, i;
+        int np = 1;
         loff_t offset = 0;
 
         ENTRY("4k aligned i/o sanity");
         while (np <= _npages) {
                 printf("%3d per xfer(total %d)...\t", np, _npages);
-                pages_io(np, offset);
+                fflush(stdout);
+                if (pages_io(np, offset) != 0)
+                        return 1;
                 np += np;
         }
         LEAVE();
+}
+
+int t50b(char *name)
+{
+        loff_t off_array[] = {1, 17, 255, 258, 4095, 4097, 8191,
+                              1024*1024*1024*1024ULL};
+        int i;
+        loff_t offset;
 
         ENTRY("4k un-aligned i/o sanity");
         for (i = 0; i < sizeof(off_array)/sizeof(loff_t); i++) {
                 offset = off_array[i];
                 printf("16 per xfer(total %d), offset %10lld...\t",
                         _npages, offset);
-                pages_io(16, offset);
+                if (pages_io(16, offset) != 0)
+                        return 1;
+        }
+
+        LEAVE();
+}
+
+enum {
+        T51_STEP = 42,
+        T51_NR   = 1000
+};
+
+/*
+ * truncate(2) checks.
+ */
+int t51(char *name)
+{
+        char file[MAX_PATH_LENGTH] = "";
+        int fd;
+        off_t size;
+        int result;
+
+        ENTRY("truncate() should truncate file to proper length");
+        snprintf(file, MAX_PATH_LENGTH, "%s/test_t51_file", lustre_path);
+
+        for (size = 0; size < T51_NR * T51_STEP; size += T51_STEP) {
+                t_echo_create(file, "");
+                if (truncate(file, size) != 0) {
+                        printf("\nerror truncating file: %s\n",strerror(errno));
+                        return(-1);
+                }
+                result = check_file_size(file, size);
+                if (result != 0)
+                        return result;
+                t_unlink(file);
+
+                t_echo_create(file, "");
+                fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
+                if (fd < 0) {
+                        printf("\nerror open file: %s\n", strerror(errno));
+                        return(-1);
+                }
+                if (ftruncate(fd, size) != 0) {
+                        printf("\nerror ftruncating file:%s\n",strerror(errno));
+                        return(-1);
+                }
+                close(fd);
+                result = check_file_size(file, size);
+                if (result != 0)
+                        return result;
+                t_unlink(file);
+                if (size % (T51_STEP * (T51_NR / 75)) == 0) {
+                        printf(".");
+                        fflush(stdout);
+                }
         }
+        printf("\n");
+        LEAVE();
+}
+/*
+ * check atime update during read
+ */
+int t52(char *name)
+{
+        char file[MAX_PATH_LENGTH] = "";
+        char buf[16];
+        struct stat statbuf;
+        time_t atime;
+        time_t diff;
+        int fd, i;
+
+        ENTRY("atime should be updated during read");
+        snprintf(file, MAX_PATH_LENGTH, "%s/test_t52_file", lustre_path);
+
+        t_echo_create(file, "check atime update during read");
+        fd = open(file, O_RDONLY);
+        if (fd < 0) {
+                printf("\nerror open file: %s\n", strerror(errno));
+                return(-1);
+        }
+        stat(file, &statbuf);
+        printf("st_atime=%s", ctime(&statbuf.st_atime));
+        atime = statbuf.st_atime;
+        for (i = 0; i < 3; i++) {
+                sleep(2);
+                read(fd, buf, sizeof(buf));
+                stat(file, &statbuf);
+                printf("st_atime=%s", ctime(&statbuf.st_atime));
+                diff = statbuf.st_atime - atime;
+                if (diff <= 0) {
+                        printf("atime doesn't updated! failed!\n");
+                        close(fd);
+                        t_unlink(file);
+                        return -1;
+                }       
+                atime = statbuf.st_atime; 
+        }
+        close(fd);
+        t_unlink(file);
         LEAVE();
 }
 
+#define NEW_TIME        10000
+int t53(char *name)
+{
+        char file[MAX_PATH_LENGTH] = "";
+        struct utimbuf times;   /* struct. buffer for utime() */
+        struct stat stat_buf;   /* struct buffer to hold file info. */
+        time_t mtime, atime;
+        ENTRY("mtime/atime should be updated by utime() call");
+        snprintf(file, MAX_PATH_LENGTH, "%s/test_t53_file", lustre_path);
+
+        t_echo_create(file, "check mtime/atime update by utime() call");
+        /* Initialize the modification and access time in the times arg */
+        times.actime = NEW_TIME+10;
+        times.modtime = NEW_TIME;
+        /* file modification/access time */
+        utime(file, &times);
+        if (stat(file, &stat_buf) < 0) {
+                printf("stat(2) of %s failed, error:%d %s\n",
+                        file, errno, strerror(errno)); 
+        }
+        mtime = stat_buf.st_mtime;
+        atime = stat_buf.st_atime;
+        if ((mtime == NEW_TIME) && (atime == NEW_TIME + 10)) {
+                t_unlink(file);
+                LEAVE();
+        }
+
+        printf("mod time %ld, expected %ld\n", mtime, (long)NEW_TIME);
+        printf("acc time %ld, expected %ld\n", atime, (long)NEW_TIME + 10);
+        t_unlink(file);
+        return (-1);
+}
+
+int t54(char *name)
+{
+        char file[MAX_PATH_LENGTH] = "";
+        struct flock lock;
+        int fd, err;
+
+        ENTRY("fcntl should return 0 when succeed in getting flock");
+        snprintf(file, MAX_PATH_LENGTH, "%s/test_t54_file", lustre_path);
+
+        t_echo_create(file, "fcntl should return 0 when succeed");
+
+        fd = open(file, O_RDWR);
+        if (fd < 0) {
+                printf("\nerror open file: %s\n", strerror(errno));
+                return(-1);
+        }
+        lock.l_type   = F_WRLCK;
+        lock.l_start  = 0;
+        lock.l_whence = 0;
+        lock.l_len    = 1;
+        if ((err = t_fcntl(fd, F_SETLKW, &lock)) != 0) {
+                fprintf(stderr, "fcntl returned: %d (%s)\n", 
+                        err, strerror(err));
+                close(fd);
+                t_unlink(file);
+                return (-1);
+        }
+
+        lock.l_type   = F_UNLCK;
+        t_fcntl(fd, F_SETLKW, &lock);
+        close(fd);
+        t_unlink(file);
+        LEAVE();
+}
+
+/* for O_DIRECTORY */
+#define _GNU_SOURCE
+
+#define STRIPE_SIZE       (2048 * 2048)
+#define STRIPE_OFFSET           0
+#define STRIPE_COUNT            1
+int t55(char *name)
+{
+        char path[MAX_PATH_LENGTH] = "";
+        char file[MAX_PATH_LENGTH] = "";
+        struct lov_user_md *lum = NULL;
+        struct lov_user_ost_data *lo = NULL;
+        int index, fd, buflen, rc;
+
+        ENTRY("setstripe/getstripe");
+        snprintf(path, MAX_PATH_LENGTH, "%s/test_t55", lustre_path);
+        snprintf(file, MAX_PATH_LENGTH, "%s/test_t55/file_t55", lustre_path);
+      
+        buflen = sizeof(struct lov_user_md);
+        buflen += STRIPE_COUNT * sizeof(struct lov_user_ost_data);
+        lum = (struct lov_user_md *)malloc(buflen);
+        if (!lum) {
+                printf("out of memory!\n");
+                return -1;
+        }
+        memset(lum, 0, buflen);
+
+        t_mkdir(path);
+        rc = llapi_file_create(path, STRIPE_SIZE, STRIPE_OFFSET,
+                               STRIPE_COUNT, LOV_PATTERN_RAID0);
+        if (rc) {
+                printf("llapi_file_create failed: rc = %d (%s) \n",
+                       rc, strerror(-rc));
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+
+        fd = open(file, O_CREAT | O_RDWR, 0644);
+        if (fd < 0) {
+                printf("open file(%s) failed: rc = %d (%s) \n)",
+                       file, fd, strerror(errno));
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+        
+        lum->lmm_magic = LOV_USER_MAGIC;
+        lum->lmm_stripe_count = STRIPE_COUNT;
+        rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, lum);
+        if (rc) {
+                printf("dir:ioctl(LL_IOC_LOV_GETSTRIPE) failed: rc = %d(%s)\n",
+                       rc, strerror(errno));
+                close(fd);
+                t_unlink(file);
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+
+        close(fd);
+
+        if (opt_verbose) {
+                printf("lmm_magic:          0x%08X\n",  lum->lmm_magic);
+                printf("lmm_object_id:      "LPX64"\n", lum->lmm_object_id);
+                printf("lmm_object_gr:      "LPX64"\n", lum->lmm_object_gr);
+                printf("lmm_stripe_count:   %u\n", (int)lum->lmm_stripe_count);
+                printf("lmm_stripe_size:    %u\n",      lum->lmm_stripe_size);
+                printf("lmm_stripe_pattern: %x\n",      lum->lmm_pattern);
+        
+                for (index = 0; index < lum->lmm_stripe_count; index++) {
+                        lo = lum->lmm_objects + index;
+                        printf("object %d:\n", index);
+                        printf("\tobject_gr:    "LPX64"\n", lo->l_object_gr);
+                        printf("\tobject_id:    "LPX64"\n", lo->l_object_id);
+                        printf("\tost_gen:      %#x\n", lo->l_ost_gen);
+                        printf("\tost_idx:      %u\n", lo->l_ost_idx);
+                }
+        }
+
+        if (lum->lmm_magic != LOV_USER_MAGIC ||
+            lum->lmm_pattern != LOV_PATTERN_RAID0 ||
+            lum->lmm_stripe_size != STRIPE_SIZE ||
+            lum->lmm_objects[0].l_ost_idx != STRIPE_OFFSET ||
+            lum->lmm_stripe_count != STRIPE_COUNT) {
+                printf("incorrect striping information!\n");
+                t_unlink(file);
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+        t_unlink(file);
+
+        /* setstripe on regular file */
+        rc = llapi_file_create(file, STRIPE_SIZE, STRIPE_OFFSET,
+                               STRIPE_COUNT, LOV_PATTERN_RAID0);
+        if (rc) {
+                printf("llapi_file_create failed: rc = %d (%s) \n",
+                       rc, strerror(-rc));
+                t_unlink(file);
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+        fd = open(file, O_RDWR, 0644);
+        if (fd < 0) {
+                printf("failed to open(%s): rc = %d (%s)\n", 
+                       file, fd, strerror(errno));
+                t_unlink(file);
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+
+        lum->lmm_magic = LOV_USER_MAGIC;
+        lum->lmm_stripe_count = STRIPE_COUNT;
+        rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, lum);
+        if (rc) {
+                printf("file:ioctl(LL_IOC_LOV_GETSTRIPE) failed: rc = %d(%s)\n",
+                       rc, strerror(errno));
+                close(fd);
+                t_unlink(file);
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+        close(fd);
+
+        if (opt_verbose) {
+                printf("lmm_magic:          0x%08X\n",  lum->lmm_magic);
+                printf("lmm_object_id:      "LPX64"\n", lum->lmm_object_id);
+                printf("lmm_object_gr:      "LPX64"\n", lum->lmm_object_gr);
+                printf("lmm_stripe_count:   %u\n", (int)lum->lmm_stripe_count);
+                printf("lmm_stripe_size:    %u\n",      lum->lmm_stripe_size);
+                printf("lmm_stripe_pattern: %x\n",      lum->lmm_pattern);
+        
+                for (index = 0; index < lum->lmm_stripe_count; index++) {
+                        lo = lum->lmm_objects + index;
+                        printf("object %d:\n", index);
+                        printf("\tobject_gr:    "LPX64"\n", lo->l_object_gr);
+                        printf("\tobject_id:    "LPX64"\n", lo->l_object_id);
+                        printf("\tost_gen:      %#x\n", lo->l_ost_gen);
+                        printf("\tost_idx:      %u\n", lo->l_ost_idx);
+                }
+        }
+
+        if (lum->lmm_magic != LOV_USER_MAGIC ||
+            lum->lmm_pattern != LOV_PATTERN_RAID0 ||
+            lum->lmm_stripe_size != STRIPE_SIZE ||
+            lum->lmm_objects[0].l_ost_idx != STRIPE_OFFSET ||
+            lum->lmm_stripe_count != STRIPE_COUNT) {
+                printf("incorrect striping information!\n");
+                t_unlink(file);
+                t_rmdir(path);
+                free(lum);
+                return -1;
+        }
+
+        t_unlink(file);
+        t_rmdir(path);
+        free(lum);
+        LEAVE();
+}
+
+/*
+ * getdirentries should return -1 and set errno to EINVAL when the size
+ * specified as an argument is too small to contain at least one entry
+ * (see bugzilla ticket 12229)
+ */
+int t56(char *name)
+{
+        int fd;
+        size_t nbytes;
+        off_t basep = 0;
+        ssize_t rc = 0;
+        struct dirent dir;
+
+        ENTRY("getdirentries should fail if nbytes is too small");
+
+        /* Set count to be very small.  The result should be EINVAL */
+        nbytes = 8;
+
+        /* open the directory and call getdirentries */
+        fd = t_opendir(lustre_path);
+
+        rc = getdirentries(fd, (char *)&dir, nbytes, &basep);
+
+        if (rc != -1) {
+                printf("Test failed: getdirentries returned %d\n", rc);
+                t_close(fd);
+                return -1;
+        }
+        if (errno != EINVAL) {
+                printf("Test failed: getdirentries returned %d but errno is set"
+                                " to %d (should be EINVAL)\n", rc, errno);
+                t_close(fd);
+                return -1;
+        }
+        t_close(fd);
+
+        LEAVE();
+}
+
+
 extern void __liblustre_setup_(void);
 extern void __liblustre_cleanup_(void);
 
+
 void usage(char *cmd)
 {
-        printf("Usage: \t%s --target mdsnid:/mdsname/profile\n", cmd);
-        printf("       \t%s --dumpfile dumpfile\n", cmd);
+        printf("\n"
+               "usage: %s [--only {test}] --target mgsnid:/fsname\n",
+               cmd);
+        printf("       %s --dumpfile dumpfile\n", cmd);
         exit(-1);
 }
 
+struct testlist {
+        int (*test)(char *name);
+        char *name;
+} testlist[] = {
+        { t1, "1" },
+        { t2, "2" },
+        { t3, "3" },
+        { t4, "4" },
+        { t6, "6" },
+        { t6b, "6b" },
+        { t7, "7" },
+        { t8, "8" },
+        { t9, "9" },
+        { t10, "10" },
+        { t11, "11" },
+        { t12, "12" },
+        { t13, "13" },
+        { t14, "14" },
+        { t15, "15" },
+        { t16, "16" },
+        { t17, "17" },
+        { t18, "18" },
+        { t18b, "t8b" },
+        { t19, "19" },
+        { t20, "20" },
+        { t21, "21" },
+        { t22, "22" },
+        { t23, "23" },
+        { t50, "50" },
+        { t50b, "50b" },
+        { t51, "51" },
+        { t53, "53" },
+        { t54, "54" },
+        { t55, "55" },
+        { t56, "56" },
+        { NULL, NULL }
+};
+
 int main(int argc, char * const argv[])
 {
-        int opt_index, c;
+        struct testlist *test;
+        int opt_index, c, rc = 0, numonly = 0;
+        char *only[100];
         static struct option long_opts[] = {
-                {"target", 1, 0, 0},
-                {"dumpfile", 1, 0, 0},
+                {"dumpfile", 1, 0, 'd'},
+                {"only", 1, 0, 'o'},
+                {"target", 1, 0, 't'},
+                {"verbose", 1, 0, 'v'},
                 {0, 0, 0, 0}
         };
 
-        if (argc <= 1)
-                usage(argv[0]);
-
-        while ((c = getopt_long(argc, argv, "", long_opts, &opt_index)) != -1) {
+        while ((c = getopt_long(argc, argv, "d:o:t:v", long_opts, &opt_index)) != -1) {
                 switch (c) {
-                case 0: {
-                        if (!optarg[0])
-                                usage(argv[0]);
-
-                        if (!strcmp(long_opts[opt_index].name, "target")) {
-                                setenv(ENV_LUSTRE_MNTTGT, optarg, 1);
-                        } else if (!strcmp(long_opts[opt_index].name, "dumpfile")) {
-                                setenv(ENV_LUSTRE_DUMPFILE, optarg, 1);
-                        } else
-                                usage(argv[0]);
+                case 'd':
+                        setenv(ENV_LUSTRE_DUMPFILE, optarg, 1);
+                        break;
+                case 'o':
+                        if (numonly == 0)
+                                printf("Only running test(s): ");
+                        printf("%s ", optarg);
+                        only[numonly++] = optarg;
+                        break;
+                case 't':
+                        setenv(ENV_LUSTRE_MNTTGT, optarg, 1);
+                        break;
+                case 'v':
+                        opt_verbose++;
                         break;
-                }
                 default:
                         usage(argv[0]);
+                        break;
                 }
         }
 
+        if (getenv(ENV_LUSTRE_MNTTGT) == NULL &&
+            getenv(ENV_LUSTRE_DUMPFILE) == NULL)
+                usage(argv[0]);
+
         if (optind != argc)
                 usage(argv[0]);
 
+        printf("\n");
+
         __liblustre_setup_();
 
-        t1();
-        t2();
-        t3();
-        t4();
-        t6();
-        t7();
-        t8();
-        t9();
-        t10();
-        t11();
-        t12();
-        t13();
-        t14();
-        t15();
-        t16();
-        t17();
-        t18();
-        t19();
-        t20();
-        t21();
-        t22();
-        t50();
-
-       printf("liblustre is about shutdown\n");
+        buf_size = _npages * PAGE_SIZE;
+        if (opt_verbose)
+                printf("allocating %d bytes buffer\n", buf_size);
+        buf_alloc = calloc(1, buf_size);
+        if (buf_alloc == NULL) {
+                fprintf(stderr, "error allocating %d\n", buf_size);
+                exit(-ENOMEM);
+        }
+
+        for (test = testlist; test->test != NULL; test++) {
+                int run = 1, i;
+
+                if (numonly > 0) {
+                        int len;
+
+                        run = 0;
+                        len = strlen(test->name);
+                        for (i = 0; i < numonly; i++) {
+                                int olen = strlen(only[i]);
+
+                                if (len < olen)
+                                        continue;
+
+                                if (strncmp(only[i], test->name, olen) == 0) {
+                                        switch(test->name[olen]) {
+                                        case '0': case '1': case '2': case '3':
+                                        case '4': case '5': case '6': case '7':
+                                        case '8': case '9':
+                                                break;
+                                        default:
+                                                run = 1;
+                                                break;
+                                        }
+                                }
+                        }
+                }
+                if (run && (rc = (test->test)(test->name)) != 0)
+                        break;
+        }
+
+        free(buf_alloc);
+
+        printf("liblustre is about to shutdown\n");
         __liblustre_cleanup_();
 
-       printf("complete successfully\n");
-       return 0;
+        printf("complete successfully\n");
+        return rc;
 }