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