Whamcloud - gitweb
7056d58d3050a8b08e965d19cf3478bc9fad2fb4
[fs/lustre-release.git] / lustre / liblustre / tests / sanity.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Lustre Light user test program
5  *
6  *  Copyright (c) 2002, 2003 Cluster File Systems, Inc.
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #define _BSD_SOURCE
25 #define _FILE_OFFSET_BITS 64
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <getopt.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <signal.h>
36 #include <errno.h>
37 #include <dirent.h>
38 #include <sys/uio.h>
39 #include <sys/time.h>
40 #include <time.h>
41
42 #include <liblustre.h>
43 #include "test_common.h"
44 #include <lustre/liblustreapi.h>
45
46 #define _npages (2048)
47
48 void *buf_alloc;
49 int buf_size;
50 int opt_verbose;
51 struct timeval start;
52
53 extern char *lustre_path;
54
55 #define ENTER(str)                                                      \
56         do {                                                            \
57                 char buf[100];                                          \
58                 int len;                                                \
59                 sprintf(buf, "===== START %s: %s ", __FUNCTION__, (str)); \
60                 len = strlen(buf);                                      \
61                 if (len < 79) {                                         \
62                         memset(buf+len, '=', 100-len);                  \
63                         buf[79] = '\n';                                 \
64                         buf[80] = 0;                                    \
65                 }                                                       \
66                 printf("%s", buf);                                      \
67                 gettimeofday(&start, NULL);                             \
68         } while (0)
69
70 #define LEAVE()                                                         \
71         do {                                                            \
72                 struct timeval stop;                                    \
73                 char buf[100] = { '\0' };                               \
74                 int len = sizeof(buf) - 1;                              \
75                 long usec;                                              \
76                 gettimeofday(&stop, NULL);                              \
77                 usec = (stop.tv_sec - start.tv_sec) * 1000000 +         \
78                        (stop.tv_usec - start.tv_usec);                  \
79                 len = snprintf(buf, len,                                \
80                                "===== END TEST %s: successfully (%gs)", \
81                                __FUNCTION__, (double)usec / 1000000);   \
82                 if (len < 79) {                                         \
83                         memset(buf+len, '=', sizeof(buf) - len);        \
84                         buf[79] = '\n';                                 \
85                         buf[80] = 0;                                    \
86                 }                                                       \
87                 printf("%s", buf);                                      \
88                 return 0;                                               \
89         } while (0)
90
91 #define MAX_PATH_LENGTH 4096
92
93 int t1(char *name)
94 {
95         char path[MAX_PATH_LENGTH] = "";
96
97         snprintf(path, MAX_PATH_LENGTH, "%s/test_t1", lustre_path);
98
99         if (opt_verbose)
100                 printf("touch+unlink %s\n", path);
101
102         t_touch(path);
103         t_unlink(path);
104         LEAVE();
105 }
106
107 int t2(char *name)
108 {
109         char path[MAX_PATH_LENGTH] = "";
110
111         ENTER("mkdir/rmdir");
112         snprintf(path, MAX_PATH_LENGTH, "%s/test_t2", lustre_path);
113
114         t_mkdir(path);
115         t_rmdir(path);
116         LEAVE();
117 }
118
119 int t3(char *name)
120 {
121         char path[MAX_PATH_LENGTH] = "";
122
123         ENTER("regular stat");
124         snprintf(path, MAX_PATH_LENGTH, "%s/test_t3", lustre_path);
125
126         t_touch(path);
127         t_check_stat(path, NULL);
128         t_unlink(path);
129         LEAVE();
130 }
131
132 int t4(char *name)
133 {
134         char path[MAX_PATH_LENGTH] = "";
135
136         ENTER("dir stat");
137         snprintf(path, MAX_PATH_LENGTH, "%s/test_t4", lustre_path);
138
139         t_mkdir(path);
140         t_check_stat(path, NULL);
141         t_rmdir(path);
142         LEAVE();
143 }
144
145 int t6(char *name)
146 {
147         char path[MAX_PATH_LENGTH] = "";
148         char path2[MAX_PATH_LENGTH] = "";
149
150         ENTER("symlink");
151         snprintf(path, MAX_PATH_LENGTH, "%s/test_t6", lustre_path);
152         snprintf(path2, MAX_PATH_LENGTH, "%s/test_t6_link", lustre_path);
153
154         t_touch(path);
155         t_symlink(path, path2);
156         t_check_stat(path2, NULL);
157         t_unlink(path2);
158         t_unlink(path);
159         LEAVE();
160 }
161
162 int t6b(char *name)
163 {
164         char path[MAX_PATH_LENGTH] = "";
165         char path2[MAX_PATH_LENGTH] = "";
166         char cwd[MAX_PATH_LENGTH] = "";
167         char *tmp;
168         int fd;
169
170         ENTER("symlink + chdir and open");
171         snprintf(path, MAX_PATH_LENGTH, "%s/test_t6b", lustre_path);
172         snprintf(path2, MAX_PATH_LENGTH, "%s/test_t6b_link", lustre_path);
173
174         t_mkdir(path);
175         t_symlink(path, path2);
176         t_check_stat(path2, NULL);
177
178         tmp = getcwd(cwd, MAX_PATH_LENGTH);
179         if (tmp == NULL) {
180                 fprintf(stderr, "current path too long to fit in "
181                         "MAX_PATH_LENGTH?\n");
182                 LEAVE();
183         }
184         t_chdir(path2);
185         t_chdir(cwd);
186         t_rmdir(path);
187         t_touch(path);
188
189         fd = t_open(path2);
190         t_close(fd);
191
192         t_unlink(path2);
193         t_unlink(path);
194         LEAVE();
195 }
196
197 int t7(char *name)
198 {
199         char path[MAX_PATH_LENGTH] = "";
200         int rc;
201
202         ENTER("mknod");
203         snprintf(path, MAX_PATH_LENGTH, "%s/test_t7", lustre_path);
204
205         if (geteuid() != 0) {
206                 rc = mknod(path, S_IFCHR | 0644, (5<<8 | 4));
207                 if (rc != -1 || errno != EPERM) {
208                         printf("mknod shouldn't success: rc %d, errno %d\n",
209                                 rc, errno);
210                 }
211         } else {
212                 t_mknod(path, S_IFCHR | 0644, 5, 4);
213                 t_check_stat(path, NULL);
214                 t_unlink(path);
215         }
216         LEAVE();
217 }
218
219 int t8(char *name)
220 {
221         char path[MAX_PATH_LENGTH] = "";
222
223         ENTER("chmod");
224         snprintf(path, MAX_PATH_LENGTH, "%s/test_t8", lustre_path);
225
226         /* Check file. */
227         t_touch(path);
228         t_chmod_raw(path, 0700);
229         t_check_stat(path, NULL);
230         t_unlink(path);
231
232         /* Check dir. */
233         t_mkdir(path);
234         t_chmod_raw(path, 0700);
235         t_check_stat(path, NULL);
236         t_rmdir(path);
237
238         LEAVE();
239 }
240
241 int t9(char *name)
242 {
243         char path[MAX_PATH_LENGTH] = "";
244         char path2[MAX_PATH_LENGTH] = "";
245
246         ENTER("hard link");
247         snprintf(path, MAX_PATH_LENGTH, "%s/test_t9", lustre_path);
248         snprintf(path2, MAX_PATH_LENGTH, "%s/test_t9_link", lustre_path);
249
250         t_touch(path);
251         t_link(path, path2);
252         t_check_stat(path, NULL);
253         t_check_stat(path2, NULL);
254         t_unlink(path);
255         t_unlink(path2);
256         LEAVE();
257 }
258
259 int t10(char *name)
260 {
261         char dir1[MAX_PATH_LENGTH] = "";
262         char dir2[MAX_PATH_LENGTH] = "";
263         char path1[MAX_PATH_LENGTH] = "";
264         char path2[MAX_PATH_LENGTH] = "";
265         char rename1[MAX_PATH_LENGTH] = "";
266         char rename2[MAX_PATH_LENGTH] = "";
267         char rename3[MAX_PATH_LENGTH] = "";
268
269         ENTER("rename");
270         snprintf(dir1, MAX_PATH_LENGTH, "%s/test_t10_dir1", lustre_path);
271         snprintf(dir2, MAX_PATH_LENGTH, "%s/test_t10_dir2", lustre_path);
272         snprintf(path1, MAX_PATH_LENGTH, "%s/test_t10_reg1", lustre_path);
273         snprintf(path2, MAX_PATH_LENGTH, "%s/test_t10_reg2", lustre_path);
274         snprintf(rename1, MAX_PATH_LENGTH, "%s/test_t10_dir1/rename1", lustre_path);
275         snprintf(rename2, MAX_PATH_LENGTH, "%s/test_t10_dir2/rename2", lustre_path);
276         snprintf(rename3, MAX_PATH_LENGTH, "%s/test_t10_dir2/rename3", lustre_path);
277
278         t_mkdir(dir1);
279         t_mkdir(dir2);
280         t_touch(path1);
281         t_touch(path2);
282         t_rename(path1, rename1);
283         t_rename(path2, rename2);
284         t_rename(rename1, rename2);
285         t_rename(dir1, rename3);
286         t_unlink(rename2);
287         t_rmdir(rename3);
288         t_rmdir(dir2);
289         LEAVE();
290 }
291
292 int t11(char *name)
293 {
294         char *base=lustre_path;
295         char path[MAX_PATH_LENGTH], path2[MAX_PATH_LENGTH];
296         int i, j, level = 5, nreg = 5;
297         ENTER("deep tree");
298
299         safe_strncpy(path, base, MAX_PATH_LENGTH);
300
301         for (i = 0; i < level; i++) {
302                 for (j = 0; j < nreg; j++) {
303                         sprintf(path2, "%s/file%d", path, j);
304                         t_touch(path2);
305                 }
306
307                 strcat(path, "/dir");
308                 t_mkdir(path);
309         }
310
311         for (i = level; i > 0; i--) {
312                 safe_strncpy(path, base, MAX_PATH_LENGTH);
313                 for (j = 1; j < i; j++)
314                         strcat(path, "/dir");
315
316                 for (j = 0; j < nreg; j++) {
317                         sprintf(path2, "%s/file%d", path, j);
318                         t_unlink(path2);
319                 }
320
321                 strcat(path, "/dir");
322                 t_rmdir(path);
323         }
324
325         LEAVE();
326 }
327
328 int t12(char *name)
329 {
330         char dir[MAX_PATH_LENGTH] = "";
331         char buf[1024*128];
332         int fd;
333         ENTER("empty directory readdir");
334         snprintf(dir, MAX_PATH_LENGTH, "%s/test_t12_dir", lustre_path);
335
336         t_mkdir(dir);
337         fd = t_opendir(dir);
338         t_ls(fd, buf, sizeof(buf));
339         t_close(fd);
340         t_rmdir(dir);
341         LEAVE();
342 }
343
344 int t13(char *name)
345 {
346         char dir[MAX_PATH_LENGTH] = "";
347         char path[1024];
348         char buf[1024];
349         const int nfiles = 20;
350         char *prefix = "test13_filename_prefix_";
351         int fd, i;
352         ENTER("multiple entries directory readdir");
353         snprintf(dir, MAX_PATH_LENGTH, "%s/test_t13_dir/", lustre_path);
354
355         t_mkdir(dir);
356         printf("Creating %d files...\n", nfiles);
357         for (i = 0; i < nfiles; i++) {
358                 sprintf(path, "%s%s%05d", dir, prefix, i);
359                 t_touch(path);
360         }
361         fd = t_opendir(dir);
362         t_ls(fd, buf, sizeof(buf));
363         t_close(fd);
364         printf("Cleanup...\n");
365         for (i = 0; i < nfiles; i++) {
366                 sprintf(path, "%s%s%05d", dir, prefix, i);
367                 t_unlink(path);
368         }
369         t_rmdir(dir);
370         LEAVE();
371 }
372
373 int t14(char *name)
374 {
375         char dir[MAX_PATH_LENGTH] = "";
376         char path[1024];
377         char buf[1024];
378         const int nfiles = 256;
379         char *prefix = "test14_filename_long_prefix_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA___";
380         cfs_dirent_t *ent;
381         int fd, i, rc, pos, index;
382         loff_t base = 0;
383         ENTER(">1 block(4k) directory readdir");
384         snprintf(dir, MAX_PATH_LENGTH, "%s/test_t14_dir/", lustre_path);
385
386         rc = mkdir(dir, 0755);
387         if (rc < 0 && errno != EEXIST) {
388                 printf("mkdir(%s) error: %s\n", dir, strerror(errno));
389                 exit(1);
390         }
391         printf("Creating %d files...\n", nfiles);
392         for (i = 0; i < nfiles; i++) {
393                 sprintf(path, "%s%s%05d", dir, prefix, i);
394                 t_touch(path);
395         }
396         fd = t_opendir(dir);
397         printf("Listing...\n");
398         index = 0;
399         while ((rc = getdirentries64(fd, buf, 1024, &base)) > 0) {
400                 pos = 0;
401                 while (pos < rc) {
402                         char *item;
403
404                         ent = (void *) buf + pos;
405                         item = (char *) ent->d_name;
406                         if (!strcmp(item, ".") || !strcmp(item, ".."))
407                                 goto iter;
408                         if (strstr(item, prefix) != item) {
409                                 printf("found bad name %s\n", item);
410                                 return(-1);
411                         }
412                         printf("[%03d]: %s\n",
413                                 index++, item + strlen(prefix));
414 iter:
415                         pos += ent->d_reclen;
416                 }
417         }
418         if (rc < 0) {
419                 printf("getdents error %d\n", rc);
420                 return(-1);
421         }
422         if (index != nfiles) {
423                 printf("get %d files != %d\n", index, nfiles);
424                 return(-1);
425         }
426         t_close(fd);
427         printf("Cleanup...\n");
428         for (i = 0; i < nfiles; i++) {
429                 sprintf(path, "%s%s%05d", dir, prefix, i);
430                 t_unlink(path);
431         }
432         t_rmdir(dir);
433         LEAVE();
434 }
435
436 int t15(char *name)
437 {
438         char file[MAX_PATH_LENGTH] = "";
439         int fd;
440         ENTER("open-stat-close");
441         snprintf(file, MAX_PATH_LENGTH, "%s/test_t15_file", lustre_path);
442
443         t_touch(file);
444         fd = t_open(file);
445         t_check_stat(file, NULL);
446         t_close(fd);
447         t_unlink(file);
448         LEAVE();
449 }
450
451 int t16(char *name)
452 {
453         char file[MAX_PATH_LENGTH] = "";
454         ENTER("small-write-read");
455         snprintf(file, MAX_PATH_LENGTH, "%s/test_t16_file", lustre_path);
456
457         t_echo_create(file, "aaaaaaaaaaaaaaaaaaaaaa");
458         t_grep(file, "aaaaaaaaaaaaaaaaaaaaaa");
459         t_unlink(file);
460         LEAVE();
461 }
462
463 int t17(char *name)
464 {
465         char file[MAX_PATH_LENGTH] = "";
466         int fd;
467         ENTER("open-unlink without close");
468         snprintf(file, MAX_PATH_LENGTH, "%s/test_t17_file", lustre_path);
469
470         fd = open(file, O_WRONLY | O_CREAT, 0666);
471         if (fd < 0) {
472                 printf("failed to create file: %s\n", strerror(errno));
473                 return(-1);
474         }
475         t_unlink(file);
476         LEAVE();
477 }
478
479 int t18(char *name)
480 {
481         char file[MAX_PATH_LENGTH] = "";
482         char buf[128];
483         int fd, i;
484         struct stat statbuf[3];
485         ENTER("write should change mtime/ctime");
486         snprintf(file, MAX_PATH_LENGTH, "%s/test_t18_file", lustre_path);
487
488         for (i = 0; i < 3; i++) {
489                 fd = open(file, O_RDWR|O_CREAT|O_APPEND, (mode_t)0666);
490                 if (fd < 0) {
491                         printf("error open file: %s\n", strerror(errno));
492                         return(-1);
493                 }
494                 if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
495                         printf("error write file\n");
496                         return(-1);
497                 }
498                 close(fd);
499                 if(stat(file, &statbuf[i]) != 0) {
500                         printf("Error stat\n");
501                         return(1);
502                 }
503                 printf("ctime %lu, mtime %lu\n",
504                         statbuf[i].st_ctime, statbuf[i].st_mtime);
505                 sleep(2);
506         }
507
508         for (i = 1; i < 3; i++) {
509                 if ((statbuf[i].st_ctime <= statbuf[i-1].st_ctime) ||
510                     (statbuf[i].st_mtime <= statbuf[i-1].st_mtime)) {
511                         printf("time error\n");
512                         return(-1);
513                 }
514         }
515         t_unlink(file);
516         LEAVE();
517 }
518
519 int t18b(char *name)
520 {
521         char file[MAX_PATH_LENGTH] = "";
522         int i;
523         struct stat statbuf[3];
524         ENTER("utime should change mtime/atime/ctime");
525         snprintf(file, MAX_PATH_LENGTH, "%s/test_t18b_file", lustre_path);
526         t_touch(file);
527
528         for (i = 0; i < 3; i++) {
529                 t_utime(file, NULL);
530                 if(stat(file, &statbuf[i]) != 0) {
531                         printf("Error stat\n");
532                         return(1);
533                 }
534                 printf("atime %lu, mtime %lu, ctime %lu\n",
535                        statbuf[i].st_atime, statbuf[i].st_mtime,
536                        statbuf[i].st_ctime);
537                 sleep(2);
538         }
539
540         for (i = 1; i < 3; i++) {
541                 if ((statbuf[i].st_atime <= statbuf[i-1].st_atime) ||
542                     (statbuf[i].st_mtime <= statbuf[i-1].st_mtime) ||
543                     (statbuf[i].st_ctime <= statbuf[i-1].st_ctime)) {
544                         printf("time error\n");
545                         return(-1);
546                 }
547         }
548         t_unlink(file);
549         LEAVE();
550 }
551
552 static int check_file_size(char *file, long long size)
553 {
554         struct stat statbuf;
555
556         if (stat(file, &statbuf) != 0) {
557                 printf("Error stat(%s)\n", file);
558                 return(1);
559         }
560         if (statbuf.st_size != size) {
561                 printf("size of %s: %ld != %lld\n", file, statbuf.st_size, size);
562                 return(-1);
563         }
564         return 0;
565 }
566
567 int t19(char *name)
568 {
569         char file[MAX_PATH_LENGTH] = "";
570         int fd;
571         int result;
572         ENTER("open(O_TRUNC) should truncate file to 0-length");
573         snprintf(file, MAX_PATH_LENGTH, "%s/test_t19_file", lustre_path);
574
575         t_echo_create(file, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
576
577         fd = open(file, O_RDWR|O_CREAT|O_TRUNC, (mode_t)0666);
578         if (fd < 0) {
579                 printf("error open file: %s\n", strerror(errno));
580                 return(-1);
581         }
582         close(fd);
583         result = check_file_size(file, 0);
584         if (result != 0)
585                 return result;
586         t_unlink(file);
587         LEAVE();
588 }
589
590 int t20(char *name)
591 {
592         char file[MAX_PATH_LENGTH] = "";
593         int fd;
594         struct iovec iov[2];
595         char buf[100];
596         ssize_t ret;
597         ENTER("trap app's general bad pointer for file i/o");
598         snprintf(file, MAX_PATH_LENGTH, "%s/test_t20_file", lustre_path);
599
600         fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
601         if (fd < 0) {
602                 printf("error open file: %s\n", strerror(errno));
603                 return(-1);
604         }
605
606         ret = write(fd, NULL, 20);
607         if (ret != -1 || errno != EFAULT) {
608                 printf("write 1: ret %ld, errno %d\n", ret, errno);
609                 return(1);
610         }
611         ret = write(fd, (void *)-1, 20);
612         if (ret != -1 || errno != EFAULT) {
613                 printf("write 2: ret %ld, errno %d\n", ret, errno);
614                 return(1);
615         }
616         iov[0].iov_base = NULL;
617         iov[0].iov_len = 10;
618         iov[1].iov_base = (void *)-1;
619         iov[1].iov_len = 10;
620         ret = writev(fd, iov, 2);
621         if (ret != -1 || errno != EFAULT) {
622                 printf("writev 1: ret %ld, errno %d\n", ret, errno);
623                 return(1);
624         }
625         iov[0].iov_base = NULL;
626         iov[0].iov_len = 0;
627         iov[1].iov_base = buf;
628         iov[1].iov_len = sizeof(buf);
629         ret = writev(fd, iov, 2);
630         if (ret != sizeof(buf)) {
631                 printf("write 3 ret %ld, error %d\n", ret, errno);
632                 return(1);
633         }
634         lseek(fd, 0, SEEK_SET);
635
636         ret = read(fd, NULL, 20);
637         if (ret != -1 || errno != EFAULT) {
638                 printf("read 1: ret %ld, errno %d\n", ret, errno);
639                 return(1);
640         }
641         ret = read(fd, (void *)-1, 20);
642         if (ret != -1 || errno != EFAULT) {
643                 printf("read 2: ret %ld, errno %d\n", ret, errno);
644                 return(1);
645         }
646         iov[0].iov_base = NULL;
647         iov[0].iov_len = 10;
648         iov[1].iov_base = (void *)-1;
649         iov[1].iov_len = 10;
650         ret = readv(fd, iov, 2);
651         if (ret != -1 || errno != EFAULT) {
652                 printf("readv 1: ret %ld, errno %d\n", ret, errno);
653                 return(1);
654         }
655         iov[0].iov_base = NULL;
656         iov[0].iov_len = 0;
657         iov[1].iov_base = buf;
658         iov[1].iov_len = sizeof(buf);
659         ret = readv(fd, iov, 2);
660         if (ret != sizeof(buf)) {
661                 printf("read 3 ret %ld, error %d\n", ret, errno);
662                 return(1);
663         }
664
665         close(fd);
666         t_unlink(file);
667         LEAVE();
668 }
669
670 int t21(char *name)
671 {
672         char file[MAX_PATH_LENGTH] = "";
673         int fd, ret;
674         struct flock lock = {
675                 .l_type = F_RDLCK,
676                 .l_whence = SEEK_SET,
677         };
678
679         ENTER("basic fcntl support");
680         snprintf(file, MAX_PATH_LENGTH, "%s/test_t21_file", lustre_path);
681
682         fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
683         if (fd < 0) {
684                 printf("error open file: %s\n", file);
685                 return(-1);
686         }
687
688         t_fcntl(fd, F_SETFL, O_APPEND);
689         if (!(ret = t_fcntl(fd, F_GETFL)) & O_APPEND) {
690                 printf("error get flag: ret %x\n", ret);
691                 return(-1);
692         }
693
694         t_fcntl(fd, F_SETLK, &lock);
695         t_fcntl(fd, F_GETLK, &lock);
696         lock.l_type = F_WRLCK;
697         t_fcntl(fd, F_SETLKW, &lock);
698         t_fcntl(fd, F_GETLK, &lock);
699         lock.l_type = F_UNLCK;
700         t_fcntl(fd, F_SETLK, &lock);
701
702         close(fd);
703         t_unlink(file);
704         LEAVE();
705 }
706
707 int t22(char *name)
708 {
709         char file[MAX_PATH_LENGTH] = "";
710         int fd;
711         char *str = "1234567890";
712         char buf[100];
713         ssize_t ret;
714         ENTER("make sure O_APPEND take effect");
715         snprintf(file, MAX_PATH_LENGTH, "%s/test_t22_file", lustre_path);
716
717         fd = open(file, O_RDWR|O_CREAT|O_APPEND, (mode_t)0666);
718         if (fd < 0) {
719                 printf("error open file: %s\n", strerror(errno));
720                 return(-1);
721         }
722
723         lseek(fd, 100, SEEK_SET);
724         ret = write(fd, str, strlen(str));
725         if (ret != strlen(str)) {
726                 printf("write 1: ret %ld, errno %d\n", ret, errno);
727                 return(1);
728         }
729
730         lseek(fd, 0, SEEK_SET);
731         ret = read(fd, buf, sizeof(buf));
732         if (ret != strlen(str)) {
733                 printf("read 1 got %ld\n", ret);
734                 return(1);
735         }
736
737         if (memcmp(buf, str, strlen(str))) {
738                 printf("read 1 data err\n");
739                 return(1);
740         }
741
742         if (fcntl(fd, F_SETFL, 0)) {
743                 printf("fcntl err: %s\n", strerror(errno));
744                 return(1);
745         }
746
747         lseek(fd, 100, SEEK_SET);
748         ret = write(fd, str, strlen(str));
749         if (ret != strlen(str)) {
750                 printf("write 2: ret %ld, errno %d\n", ret, errno);
751                 return(1);
752         }
753
754         lseek(fd, 100, SEEK_SET);
755         ret = read(fd, buf, sizeof(buf));
756         if (ret != strlen(str)) {
757                 printf("read 2 got %ld\n", ret);
758                 return(1);
759         }
760
761         if (memcmp(buf, str, strlen(str))) {
762                 printf("read 2 data err\n");
763                 return(1);
764         }
765
766         close(fd);
767         t_unlink(file);
768         LEAVE();
769 }
770
771 int t23(char *name)
772 {
773         char path[MAX_PATH_LENGTH];
774         int fd;
775         off_t ret;
776         off_t off;
777
778         ENTER("handle seek > 2GB");
779         snprintf(path, MAX_PATH_LENGTH, "%s/f%s", lustre_path, name);
780
781         fd = open(path, O_WRONLY | O_CREAT | O_LARGEFILE, 0666);
782         if (fd < 0) {
783                 printf("failed to create file %s: %s\n", path, strerror(errno));
784                 return(-1);
785         }
786
787         off = 2048ULL * 1024 * 1024 - buf_size / 2;
788         ret = lseek(fd, off, SEEK_SET);
789         if (ret != off) {
790                 printf("seek error for initial %llu != %llu\n",
791                        ret, (long long)off);
792                 return -1;
793         }
794
795         ret = write(fd, buf_alloc, buf_size);
796         if (ret != buf_size) {
797                 printf("write error for %d != %llubytes @ %llu\n",
798                        buf_size, ret, (long long)off);
799                 if (ret == -1)
800                         perror("write");
801                 return -1;
802         }
803
804         ret = lseek(fd, off, SEEK_SET);
805         if (ret != off) {
806                 printf("seek < 2GB error for %llu != %llu\n",
807                        ret, (long long)off);
808                 if (ret == -1)
809                         perror("seek < 2GB");
810                 return -1;
811         }
812
813         ret = lseek(fd, off + buf_size - 2, SEEK_SET);
814         if (ret != off + buf_size - 2) {
815                 printf("seek > 2GB error for %llu != %llu\n",
816                        ret, (long long)off);
817                 if (ret == -1)
818                         perror("seek > 2GB");
819                 return -1;
820         }
821
822         ret = lseek(fd, -buf_size + 2, SEEK_CUR);
823         if (ret != off) {
824                 printf("relative seek error for %d %llu != %llu\n",
825                        -buf_size + 2, ret, off);
826                 if (ret == -1)
827                         perror("relative seek");
828                 return -1;
829         }
830
831         ret = lseek(fd, 0, SEEK_END);
832         if (ret != off + buf_size) {
833                 printf("end seek error for %llu != %llu\n",
834                        ret, (long long)off + buf_size);
835                 if (ret == -1)
836                         perror("end seek");
837                 return -1;
838         }
839
840         ret = lseek(fd, 0, SEEK_SET);
841         if (ret != 0) {
842                 printf("seek 0 error for %llu != 0\n", ret);
843                 if (ret == -1)
844                         perror("seek 0");
845                 return -1;
846         }
847
848         off = 2048ULL * 1024 * 1024, SEEK_SET;
849         ret = lseek(fd, off, SEEK_SET);
850         if (ret != off) {
851                 printf("seek 2GB error for %llu != %llu\n", ret, off);
852                 if (ret == -1)
853                         perror("seek 2GB");
854                 return -1;
855         }
856
857         close(fd);
858         t_unlink(path);
859         LEAVE();
860 }
861
862 /* pos:   i/o start from
863  * xfer:  npages per transfer
864  */
865 static int pages_io(int xfer, loff_t pos)
866 {
867         char path[MAX_PATH_LENGTH] = "";
868
869         int check_sum[_npages] = {0,}, *buf;
870         int fd, rc, i, j, data_error = 0;
871         struct timeval tw1, tw2, tr1, tr2;
872         double tw, tr;
873         loff_t ret;
874
875         snprintf(path, MAX_PATH_LENGTH, "%s/test_t50", lustre_path);
876
877         memset(buf_alloc, 0, buf_size);
878
879         /* create sample data */
880         for (i = 0, buf = buf_alloc; i < _npages; i++) {
881                 for (j = 0; j < CFS_PAGE_SIZE/sizeof(int); j++, buf++) {
882                         *buf = rand();
883                 }
884         }
885
886         /* compute checksum */
887         for (i = 0, buf = buf_alloc; i < _npages; i++) {
888                 for (j = 0; j < CFS_PAGE_SIZE/sizeof(int); j++, buf++) {
889                         check_sum[i] += *buf;
890                 }
891         }
892
893         unlink(path);
894         t_touch(path);
895
896         fd = t_open(path);
897
898         /* write */
899         ret = lseek(fd, pos, SEEK_SET);
900         if (ret != pos) {
901                 perror("write seek");
902                 return 1;
903         }
904         gettimeofday(&tw1, NULL);
905         for (i = 0, buf = buf_alloc; i < _npages;
906              i += xfer, buf += xfer * CFS_PAGE_SIZE / sizeof(int)) {
907                 rc = write(fd, buf, CFS_PAGE_SIZE * xfer);
908                 if (rc != CFS_PAGE_SIZE * xfer) {
909                         printf("write error (i %d, rc %d): %s\n", i, rc,
910                                strerror(errno));
911                         return(1);
912                 }
913         }
914         gettimeofday(&tw2, NULL);
915
916         memset(buf_alloc, 0, buf_size);
917
918         /* read */
919         ret = lseek(fd, pos, SEEK_SET);
920         if (ret != pos) {
921                 perror("read seek");
922                 return 1;
923         }
924         gettimeofday(&tr1, NULL);
925         for (i = 0, buf = buf_alloc; i < _npages;
926              i += xfer, buf += xfer * CFS_PAGE_SIZE / sizeof(int)) {
927                 rc = read(fd, buf, CFS_PAGE_SIZE * xfer);
928                 if (rc != CFS_PAGE_SIZE * xfer) {
929                         printf("read error (i %d, rc %d): %s\n", i, rc,
930                                strerror(errno));
931                         return(1);
932                 }
933         }
934         gettimeofday(&tr2, NULL);
935
936         /* compute checksum */
937         for (i = 0, buf = buf_alloc; i < _npages; i++) {
938                 int sum = 0;
939                 for (j = 0; j < CFS_PAGE_SIZE/sizeof(int); j++, buf++) {
940                         sum += *buf;
941                 }
942                 if (sum != check_sum[i]) {
943                         data_error = 1;
944                         printf("chunk %d checksum error expected %#x got %#x\n",
945                                 i, check_sum[i], sum);
946                 }
947         }
948
949         t_close(fd);
950         t_unlink(path);
951         tw = (tw2.tv_sec - tw1.tv_sec) * 1000000 + (tw2.tv_usec - tw1.tv_usec);
952         tr = (tr2.tv_sec - tr1.tv_sec) * 1000000 + (tr2.tv_usec - tr1.tv_usec);
953         printf(" (R:%.3fM/s, W:%.3fM/s)\n",
954                 (_npages * CFS_PAGE_SIZE) / (tw / 1000000.0) / (1024 * 1024),
955                 (_npages * CFS_PAGE_SIZE) / (tr / 1000000.0) / (1024 * 1024));
956
957         if (data_error)
958                 return 1;
959
960         return 0;
961 }
962
963 int t50(char *name)
964 {
965         int np = 1;
966         loff_t offset = 0;
967
968         ENTER("4k aligned i/o sanity");
969         while (np <= _npages) {
970                 printf("%3d per xfer(total %d)...\t", np, _npages);
971                 fflush(stdout);
972                 if (pages_io(np, offset) != 0)
973                         return 1;
974                 np += np;
975         }
976         LEAVE();
977 }
978
979 int t50b(char *name)
980 {
981         loff_t off_array[] = {1, 17, 255, 258, 4095, 4097, 8191,
982                               1024*1024*1024*1024ULL};
983         int i;
984         long long offset;
985
986         ENTER("4k un-aligned i/o sanity");
987         for (i = 0; i < sizeof(off_array)/sizeof(loff_t); i++) {
988                 offset = off_array[i];
989                 printf("16 per xfer(total %d), offset %10lld...\t",
990                         _npages, offset);
991                 if (pages_io(16, offset) != 0)
992                         return 1;
993         }
994
995         LEAVE();
996 }
997
998 enum {
999         T51_STEP = 42,
1000         T51_NR   = 1000
1001 };
1002
1003 /*
1004  * truncate(2) checks.
1005  */
1006 int t51(char *name)
1007 {
1008         char file[MAX_PATH_LENGTH] = "";
1009         int fd;
1010         long long size;
1011         int result;
1012
1013         ENTER("truncate() should truncate file to proper length");
1014         snprintf(file, MAX_PATH_LENGTH, "%s/test_t51_file", lustre_path);
1015
1016         for (size = 0; size < T51_NR * T51_STEP; size += T51_STEP) {
1017                 t_echo_create(file, "");
1018                 if (truncate(file, size) != 0) {
1019                         printf("\nerror truncating file: %s\n",strerror(errno));
1020                         return(-1);
1021                 }
1022                 result = check_file_size(file, size);
1023                 if (result != 0)
1024                         return result;
1025                 t_unlink(file);
1026
1027                 t_echo_create(file, "");
1028                 fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
1029                 if (fd < 0) {
1030                         printf("\nerror open file: %s\n", strerror(errno));
1031                         return(-1);
1032                 }
1033                 if (ftruncate(fd, size) != 0) {
1034                         printf("\nerror ftruncating file:%s\n",strerror(errno));
1035                         return(-1);
1036                 }
1037                 close(fd);
1038                 result = check_file_size(file, size);
1039                 if (result != 0)
1040                         return result;
1041                 t_unlink(file);
1042                 if (size % (T51_STEP * (T51_NR / 75)) == 0) {
1043                         printf(".");
1044                         fflush(stdout);
1045                 }
1046         }
1047         printf("\n");
1048         LEAVE();
1049 }
1050 /*
1051  * check atime update during read
1052  */
1053 int t52(char *name)
1054 {
1055         char file[MAX_PATH_LENGTH] = "";
1056         char buf[16];
1057         struct stat statbuf;
1058         time_t atime;
1059         time_t diff;
1060         int fd, i;
1061
1062         ENTER("atime should be updated during read");
1063         snprintf(file, MAX_PATH_LENGTH, "%s/test_t52_file", lustre_path);
1064
1065         t_echo_create(file, "check atime update during read");
1066         fd = open(file, O_RDONLY);
1067         if (fd < 0) {
1068                 printf("\nerror open file: %s\n", strerror(errno));
1069                 return(-1);
1070         }
1071         stat(file, &statbuf);
1072         printf("st_atime=%s", ctime(&statbuf.st_atime));
1073         atime = statbuf.st_atime;
1074         for (i = 0; i < 3; i++) {
1075                 sleep(2);
1076                 read(fd, buf, sizeof(buf));
1077                 stat(file, &statbuf);
1078                 printf("st_atime=%s", ctime(&statbuf.st_atime));
1079                 diff = statbuf.st_atime - atime;
1080                 if (diff <= 0) {
1081                         printf("atime doesn't updated! failed!\n");
1082                         close(fd);
1083                         t_unlink(file);
1084                         return -1;
1085                 }       
1086                 atime = statbuf.st_atime; 
1087         }
1088         close(fd);
1089         t_unlink(file);
1090         LEAVE();
1091 }
1092
1093 #define NEW_TIME        10000
1094 int t53(char *name)
1095 {
1096         char file[MAX_PATH_LENGTH] = "";
1097         struct utimbuf times;   /* struct. buffer for utime() */
1098         struct stat stat_buf;   /* struct buffer to hold file info. */
1099         time_t mtime, atime;
1100  
1101         ENTER("mtime/atime should be updated by utime() call");
1102         snprintf(file, MAX_PATH_LENGTH, "%s/test_t53_file", lustre_path);
1103
1104         t_echo_create(file, "check mtime/atime update by utime() call");
1105  
1106         /* Initialize the modification and access time in the times arg */
1107         times.actime = NEW_TIME+10;
1108         times.modtime = NEW_TIME;
1109  
1110         /* file modification/access time */
1111         utime(file, &times);
1112  
1113         if (stat(file, &stat_buf) < 0) {
1114                 printf("stat(2) of %s failed, error:%d %s\n",
1115                         file, errno, strerror(errno)); 
1116         }
1117         mtime = stat_buf.st_mtime;
1118         atime = stat_buf.st_atime;
1119  
1120         if ((mtime == NEW_TIME) && (atime == NEW_TIME + 10)) {
1121                 t_unlink(file);
1122                 LEAVE();
1123         }
1124
1125         printf("mod time %ld, expected %ld\n", mtime, (long)NEW_TIME);
1126         printf("acc time %ld, expected %ld\n", atime, (long)NEW_TIME + 10);
1127  
1128         t_unlink(file);
1129         return (-1);
1130 }
1131
1132 int t54(char *name)
1133 {
1134         char file[MAX_PATH_LENGTH] = "";
1135         struct flock lock;
1136         int fd, err;
1137
1138         ENTER("fcntl should return 0 when succeed in getting flock");
1139         snprintf(file, MAX_PATH_LENGTH, "%s/test_t54_file", lustre_path);
1140
1141         t_echo_create(file, "fcntl should return 0 when succeed");
1142
1143         fd = open(file, O_RDWR);
1144         if (fd < 0) {
1145                 printf("\nerror open file: %s\n", strerror(errno));
1146                 return(-1);
1147         }
1148         lock.l_type   = F_WRLCK;
1149         lock.l_start  = 0;
1150         lock.l_whence = 0;
1151         lock.l_len    = 1;
1152         if ((err = t_fcntl(fd, F_SETLKW, &lock)) != 0) {
1153                 fprintf(stderr, "fcntl returned: %d (%s)\n", 
1154                         err, strerror(err));
1155                 close(fd);
1156                 t_unlink(file);
1157                 return (-1);
1158         }
1159
1160         lock.l_type   = F_UNLCK;
1161         t_fcntl(fd, F_SETLKW, &lock);
1162         close(fd);
1163         t_unlink(file);
1164         LEAVE();
1165 }
1166
1167 /* for O_DIRECTORY */
1168 #ifndef _GNU_SOURCE
1169 #define _GNU_SOURCE
1170 #endif
1171
1172 #define STRIPE_SIZE       (2048 * 2048)
1173 #define STRIPE_OFFSET           0
1174 #define STRIPE_COUNT            1
1175 int t55(char *name)
1176 {
1177         char path[MAX_PATH_LENGTH] = "";
1178         char file[MAX_PATH_LENGTH] = "";
1179         struct lov_user_md *lum = NULL;
1180         struct lov_user_ost_data *lo = NULL;
1181         int index, fd, buflen, rc;
1182
1183         ENTER("setstripe/getstripe");
1184         snprintf(path, MAX_PATH_LENGTH, "%s/test_t55", lustre_path);
1185         snprintf(file, MAX_PATH_LENGTH, "%s/test_t55/file_t55", lustre_path);
1186       
1187         buflen = sizeof(struct lov_user_md);
1188         buflen += STRIPE_COUNT * sizeof(struct lov_user_ost_data);
1189         lum = (struct lov_user_md *)malloc(buflen);
1190         if (!lum) {
1191                 printf("out of memory!\n");
1192                 return -1;
1193         }
1194         memset(lum, 0, buflen);
1195
1196         t_mkdir(path);
1197         rc = llapi_file_create(path, STRIPE_SIZE, STRIPE_OFFSET,
1198                                STRIPE_COUNT, LOV_PATTERN_RAID0);
1199         if (rc) {
1200                 printf("llapi_file_create failed: rc = %d (%s) \n",
1201                        rc, strerror(-rc));
1202                 t_rmdir(path);
1203                 free(lum);
1204                 return -1;
1205         }
1206
1207         fd = open(file, O_CREAT | O_RDWR, 0644);
1208         if (fd < 0) {
1209                 printf("open file(%s) failed: rc = %d (%s) \n)",
1210                        file, fd, strerror(errno));
1211                 t_rmdir(path);
1212                 free(lum);
1213                 return -1;
1214         }
1215         
1216         lum->lmm_magic = LOV_USER_MAGIC;
1217         lum->lmm_stripe_count = STRIPE_COUNT;
1218         rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, lum);
1219         if (rc) {
1220                 printf("dir:ioctl(LL_IOC_LOV_GETSTRIPE) failed: rc = %d(%s)\n",
1221                        rc, strerror(errno));
1222                 close(fd);
1223                 t_unlink(file);
1224                 t_rmdir(path);
1225                 free(lum);
1226                 return -1;
1227         }
1228
1229         close(fd);
1230
1231         if (opt_verbose) {
1232                 printf("lmm_magic:          0x%08X\n",  lum->lmm_magic);
1233                 printf("lmm_object_id:      "LPX64"\n", lum->lmm_object_id);
1234                 printf("lmm_object_gr:      "LPX64"\n", lum->lmm_object_gr);
1235                 printf("lmm_stripe_count:   %u\n", (int)lum->lmm_stripe_count);
1236                 printf("lmm_stripe_size:    %u\n",      lum->lmm_stripe_size);
1237                 printf("lmm_stripe_pattern: %x\n",      lum->lmm_pattern);
1238         
1239                 for (index = 0; index < lum->lmm_stripe_count; index++) {
1240                         lo = lum->lmm_objects + index;
1241                         printf("object %d:\n", index);
1242                         printf("\tobject_gr:    "LPX64"\n", lo->l_object_gr);
1243                         printf("\tobject_id:    "LPX64"\n", lo->l_object_id);
1244                         printf("\tost_gen:      %#x\n", lo->l_ost_gen);
1245                         printf("\tost_idx:      %u\n", lo->l_ost_idx);
1246                 }
1247         }
1248
1249         if (lum->lmm_magic != LOV_USER_MAGIC ||
1250             lum->lmm_pattern != LOV_PATTERN_RAID0 ||
1251             lum->lmm_stripe_size != STRIPE_SIZE ||
1252             lum->lmm_objects[0].l_ost_idx != STRIPE_OFFSET ||
1253             lum->lmm_stripe_count != STRIPE_COUNT) {
1254                 printf("incorrect striping information!\n");
1255                 t_unlink(file);
1256                 t_rmdir(path);
1257                 free(lum);
1258                 return -1;
1259         }
1260         t_unlink(file);
1261
1262         /* setstripe on regular file */
1263         rc = llapi_file_create(file, STRIPE_SIZE, STRIPE_OFFSET,
1264                                STRIPE_COUNT, LOV_PATTERN_RAID0);
1265         if (rc) {
1266                 printf("llapi_file_create failed: rc = %d (%s) \n",
1267                        rc, strerror(-rc));
1268                 t_unlink(file);
1269                 t_rmdir(path);
1270                 free(lum);
1271                 return -1;
1272         }
1273         fd = open(file, O_RDWR, 0644);
1274         if (fd < 0) {
1275                 printf("failed to open(%s): rc = %d (%s)\n", 
1276                        file, fd, strerror(errno));
1277                 t_unlink(file);
1278                 t_rmdir(path);
1279                 free(lum);
1280                 return -1;
1281         }
1282
1283         lum->lmm_magic = LOV_USER_MAGIC;
1284         lum->lmm_stripe_count = STRIPE_COUNT;
1285         rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, lum);
1286         if (rc) {
1287                 printf("file:ioctl(LL_IOC_LOV_GETSTRIPE) failed: rc = %d(%s)\n",
1288                        rc, strerror(errno));
1289                 close(fd);
1290                 t_unlink(file);
1291                 t_rmdir(path);
1292                 free(lum);
1293                 return -1;
1294         }
1295         close(fd);
1296
1297         if (opt_verbose) {
1298                 printf("lmm_magic:          0x%08X\n",  lum->lmm_magic);
1299                 printf("lmm_object_id:      "LPX64"\n", lum->lmm_object_id);
1300                 printf("lmm_object_gr:      "LPX64"\n", lum->lmm_object_gr);
1301                 printf("lmm_stripe_count:   %u\n", (int)lum->lmm_stripe_count);
1302                 printf("lmm_stripe_size:    %u\n",      lum->lmm_stripe_size);
1303                 printf("lmm_stripe_pattern: %x\n",      lum->lmm_pattern);
1304         
1305                 for (index = 0; index < lum->lmm_stripe_count; index++) {
1306                         lo = lum->lmm_objects + index;
1307                         printf("object %d:\n", index);
1308                         printf("\tobject_gr:    "LPX64"\n", lo->l_object_gr);
1309                         printf("\tobject_id:    "LPX64"\n", lo->l_object_id);
1310                         printf("\tost_gen:      %#x\n", lo->l_ost_gen);
1311                         printf("\tost_idx:      %u\n", lo->l_ost_idx);
1312                 }
1313         }
1314
1315         if (lum->lmm_magic != LOV_USER_MAGIC ||
1316             lum->lmm_pattern != LOV_PATTERN_RAID0 ||
1317             lum->lmm_stripe_size != STRIPE_SIZE ||
1318             lum->lmm_objects[0].l_ost_idx != STRIPE_OFFSET ||
1319             lum->lmm_stripe_count != STRIPE_COUNT) {
1320                 printf("incorrect striping information!\n");
1321                 t_unlink(file);
1322                 t_rmdir(path);
1323                 free(lum);
1324                 return -1;
1325         }
1326
1327         t_unlink(file);
1328         t_rmdir(path);
1329         free(lum);
1330         LEAVE();
1331 }
1332
1333 /*
1334  * getdirentries should return -1 and set errno to EINVAL when the size
1335  * specified as an argument is too small to contain at least one entry
1336  * (see bugzilla ticket 12229)
1337  */
1338 int t56(char *name)
1339 {
1340         int fd;
1341         size_t nbytes;
1342         off_t basep = 0;
1343         ssize_t rc = 0;
1344         cfs_dirent_t dir;
1345
1346         ENTER("getdirentries should fail if nbytes is too small");
1347
1348         /* Set count to be very small.  The result should be EINVAL */
1349         nbytes = 8;
1350
1351         /* open the directory and call getdirentries */
1352         fd = t_opendir(lustre_path);
1353
1354         rc = getdirentries(fd, (char *)&dir, nbytes, &basep);
1355
1356         if (rc != -1) {
1357                 printf("Test failed: getdirentries returned %ld\n", rc);
1358                 t_close(fd);
1359                 return -1;
1360         }
1361         if (errno != EINVAL) {
1362                 printf("Test failed: getdirentries returned %ld but errno is set"
1363                                 " to %d (should be EINVAL)\n", rc, errno);
1364                 t_close(fd);
1365                 return -1;
1366         }
1367         t_close(fd);
1368
1369         LEAVE();
1370 }
1371
1372 extern void __liblustre_setup_(void);
1373 extern void __liblustre_cleanup_(void);
1374
1375
1376 void usage(char *cmd)
1377 {
1378         printf("\n"
1379                "usage: %s [--only {test}] --target mgsnid:/fsname\n",
1380                cmd);
1381         printf("       %s --dumpfile dumpfile\n", cmd);
1382         exit(-1);
1383 }
1384
1385 struct testlist {
1386         int (*test)(char *name);
1387         char *name;
1388 } testlist[] = {
1389         { t1, "1" },
1390         { t2, "2" },
1391         { t3, "3" },
1392         { t4, "4" },
1393         { t6, "6" },
1394         { t6b, "6b" },
1395         { t7, "7" },
1396         { t8, "8" },
1397         { t9, "9" },
1398         { t10, "10" },
1399         { t11, "11" },
1400         { t12, "12" },
1401         { t13, "13" },
1402         { t14, "14" },
1403         { t15, "15" },
1404         { t16, "16" },
1405         { t17, "17" },
1406         { t18, "18" },
1407         { t18b, "t8b" },
1408         { t19, "19" },
1409         { t20, "20" },
1410         { t21, "21" },
1411         { t22, "22" },
1412         { t23, "23" },
1413         { t50, "50" },
1414         { t50b, "50b" },
1415         { t51, "51" },
1416         { t53, "53" },
1417         { t54, "54" },
1418         { t55, "55" },
1419         { t56, "56" },
1420         { NULL, NULL }
1421 };
1422
1423 int main(int argc, char * const argv[])
1424 {
1425         struct testlist *test;
1426         int opt_index, c, rc = 0, numonly = 0;
1427         char *only[100];
1428         static struct option long_opts[] = {
1429                 {"dumpfile", 1, 0, 'd'},
1430                 {"only", 1, 0, 'o'},
1431                 {"target", 1, 0, 't'},
1432                 {"verbose", 1, 0, 'v'},
1433                 {0, 0, 0, 0}
1434         };
1435
1436         while ((c = getopt_long(argc, argv, "d:o:t:v", long_opts, &opt_index)) != -1) {
1437                 switch (c) {
1438                 case 'd':
1439                         setenv(ENV_LUSTRE_DUMPFILE, optarg, 1);
1440                         break;
1441                 case 'o':
1442                         if (numonly == 0)
1443                                 printf("Only running test(s): ");
1444                         printf("%s ", optarg);
1445                         only[numonly++] = optarg;
1446                         break;
1447                 case 't':
1448                         setenv(ENV_LUSTRE_MNTTGT, optarg, 1);
1449                         break;
1450                 case 'v':
1451                         opt_verbose++;
1452                         break;
1453                 default:
1454                         usage(argv[0]);
1455                         break;
1456                 }
1457         }
1458
1459         if (getenv(ENV_LUSTRE_MNTTGT) == NULL &&
1460             getenv(ENV_LUSTRE_DUMPFILE) == NULL)
1461                 usage(argv[0]);
1462
1463         if (optind != argc)
1464                 usage(argv[0]);
1465
1466         printf("\n");
1467
1468         __liblustre_setup_();
1469
1470         buf_size = _npages * CFS_PAGE_SIZE;
1471         if (opt_verbose)
1472                 printf("allocating %d bytes buffer\n", buf_size);
1473         buf_alloc = calloc(1, buf_size);
1474         if (buf_alloc == NULL) {
1475                 fprintf(stderr, "error allocating %d\n", buf_size);
1476                 exit(-ENOMEM);
1477         }
1478
1479         for (test = testlist; test->test != NULL; test++) {
1480                 int run = 1, i;
1481
1482                 if (numonly > 0) {
1483                         int len;
1484
1485                         run = 0;
1486                         len = strlen(test->name);
1487                         for (i = 0; i < numonly; i++) {
1488                                 int olen = strlen(only[i]);
1489
1490                                 if (len < olen)
1491                                         continue;
1492
1493                                 if (strncmp(only[i], test->name, olen) == 0) {
1494                                         switch(test->name[olen]) {
1495                                         case '0': case '1': case '2': case '3':
1496                                         case '4': case '5': case '6': case '7':
1497                                         case '8': case '9':
1498                                                 break;
1499                                         default:
1500                                                 run = 1;
1501                                                 break;
1502                                         }
1503                                 }
1504                         }
1505                 }
1506                 if (run && (rc = (test->test)(test->name)) != 0)
1507                         break;
1508         }
1509
1510         free(buf_alloc);
1511
1512         printf("liblustre is about to shutdown\n");
1513         __liblustre_cleanup_();
1514
1515         printf("complete successfully\n");
1516         return rc;
1517 }