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