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