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