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