Whamcloud - gitweb
LU-5456 hsm: hold inode mutex around ll_setattr_raw()
[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  * Copyright (c) 2013, Intel Corporation.
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/lustreapi.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         struct dirent64 *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         ret = t_fcntl(fd, F_GETFL);
711         if ((ret & O_APPEND) == 0) {
712                 printf("error get flag: ret %o\n", ret);
713                 return(-1);
714         }
715
716         t_fcntl(fd, F_SETLK, &lock);
717         t_fcntl(fd, F_GETLK, &lock);
718         lock.l_type = F_WRLCK;
719         t_fcntl(fd, F_SETLKW, &lock);
720         t_fcntl(fd, F_GETLK, &lock);
721         lock.l_type = F_UNLCK;
722         t_fcntl(fd, F_SETLK, &lock);
723
724         close(fd);
725         t_unlink(file);
726         LEAVE();
727 }
728
729 int t22(char *name)
730 {
731         char file[MAX_PATH_LENGTH] = "";
732         int fd;
733         char *str = "1234567890";
734         char buf[100];
735         long ret;
736         ENTER("make sure O_APPEND take effect");
737         snprintf(file, MAX_PATH_LENGTH, "%s/test_t22_file", lustre_path);
738
739         fd = open(file, O_TRUNC|O_RDWR|O_CREAT|O_APPEND, (mode_t)0666);
740         if (fd < 0) {
741                 printf("error open file: %s\n", strerror(errno));
742                 return(-1);
743         }
744
745         lseek(fd, 100, SEEK_SET);
746         ret = write(fd, str, strlen(str));
747         if (ret != strlen(str)) {
748                 printf("write 1: ret %lld, errno %d\n", (long long)ret, errno);
749                 return(1);
750         }
751
752         lseek(fd, 0, SEEK_SET);
753         ret = read(fd, buf, sizeof(buf));
754         if (ret != strlen(str)) {
755                 printf("read 1: ret %lld\n", (long long)ret);
756                 return(1);
757         }
758
759         if (memcmp(buf, str, strlen(str))) {
760                 printf("read 1 data err\n");
761                 return(1);
762         }
763
764         if (fcntl(fd, F_SETFL, 0)) {
765                 printf("fcntl err: %s\n", strerror(errno));
766                 return(1);
767         }
768
769         lseek(fd, 100, SEEK_SET);
770         ret = write(fd, str, strlen(str));
771         if (ret != strlen(str)) {
772                 printf("write 2: ret %lld, errno %d\n", (long long)ret, errno);
773                 return(1);
774         }
775
776         lseek(fd, 100, SEEK_SET);
777         ret = read(fd, buf, sizeof(buf));
778         if (ret != strlen(str)) {
779                 printf("read 2: ret %lld\n", (long long)ret);
780                 return(1);
781         }
782
783         if (memcmp(buf, str, strlen(str))) {
784                 printf("read 2 data err\n");
785                 return(1);
786         }
787
788         close(fd);
789         t_unlink(file);
790         LEAVE();
791 }
792
793 int t23(char *name)
794 {
795         char path[MAX_PATH_LENGTH];
796         int fd;
797         long long ret;
798         loff_t off;
799
800         ENTER("handle seek > 2GB");
801         snprintf(path, MAX_PATH_LENGTH, "%s/f%s", lustre_path, name);
802
803         fd = open(path, O_WRONLY | O_CREAT | O_LARGEFILE, 0666);
804         if (fd < 0) {
805                 printf("failed to create file %s: %s\n", path, strerror(errno));
806                 return(-1);
807         }
808
809         off = 2048ULL * 1024 * 1024 - buf_size / 2;
810         ret = lseek(fd, off, SEEK_SET);
811         if (ret != off) {
812                 printf("seek error for initial %llu != %llu\n",
813                        ret, (long long)off);
814                 return -1;
815         }
816
817         ret = write(fd, buf_alloc, buf_size);
818         if (ret != buf_size) {
819                 printf("write error for %d != %llubytes @ %llu\n",
820                        buf_size, ret, (long long)off);
821                 if (ret == -1)
822                         perror("write");
823                 return -1;
824         }
825
826         ret = lseek(fd, off, SEEK_SET);
827         if (ret != off) {
828                 printf("seek < 2GB error for %llu != %llu\n",
829                        ret, (long long)off);
830                 if (ret == -1)
831                         perror("seek < 2GB");
832                 return -1;
833         }
834
835         ret = lseek(fd, off + buf_size - 2, SEEK_SET);
836         if (ret != off + buf_size - 2) {
837                 printf("seek > 2GB error for %llu != %llu\n",
838                        ret, (long long)off);
839                 if (ret == -1)
840                         perror("seek > 2GB");
841                 return -1;
842         }
843
844         ret = lseek(fd, -buf_size + 2, SEEK_CUR);
845         if (ret != off) {
846                 printf("relative seek error for %d %llu != %llu\n",
847                        -buf_size + 2, ret, (unsigned long long) off);
848                 if (ret == -1)
849                         perror("relative seek");
850                 return -1;
851         }
852
853         ret = lseek(fd, 0, SEEK_END);
854         if (ret != off + buf_size) {
855                 printf("end seek error for %llu != %llu\n",
856                        ret, (long long)off + buf_size);
857                 if (ret == -1)
858                         perror("end seek");
859                 return -1;
860         }
861
862         ret = lseek(fd, 0, SEEK_SET);
863         if (ret != 0) {
864                 printf("seek 0 error for %llu != 0\n", ret);
865                 if (ret == -1)
866                         perror("seek 0");
867                 return -1;
868         }
869
870         off = 2048ULL * 1024 * 1024, SEEK_SET;
871         ret = lseek(fd, off, SEEK_SET);
872         if (ret != off) {
873                 printf("seek 2GB error for %llu != %llu\n", ret, (unsigned long long) off);
874                 if (ret == -1)
875                         perror("seek 2GB");
876                 return -1;
877         }
878
879         close(fd);
880         t_unlink(path);
881         LEAVE();
882 }
883
884 /* pos:   i/o start from
885  * xfer:  npages per transfer
886  */
887 static int pages_io(int xfer, loff_t pos)
888 {
889         char path[MAX_PATH_LENGTH] = "";
890
891         int check_sum[_npages] = {0,}, *buf;
892         int fd, rc, i, j, data_error = 0;
893         struct timeval tw1, tw2, tr1, tr2;
894         double tw, tr;
895         loff_t ret;
896
897         snprintf(path, MAX_PATH_LENGTH, "%s/test_t50", lustre_path);
898
899         memset(buf_alloc, 0, buf_size);
900
901         /* create sample data */
902         for (i = 0, buf = buf_alloc; i < _npages; i++) {
903                 for (j = 0; j < PAGE_CACHE_SIZE/sizeof(int); j++, buf++) {
904                         *buf = rand();
905                 }
906         }
907
908         /* compute checksum */
909         for (i = 0, buf = buf_alloc; i < _npages; i++) {
910                 for (j = 0; j < PAGE_CACHE_SIZE/sizeof(int); j++, buf++) {
911                         check_sum[i] += *buf;
912                 }
913         }
914
915         unlink(path);
916         t_touch(path);
917
918         fd = t_open(path);
919
920         /* write */
921         ret = lseek(fd, pos, SEEK_SET);
922         if (ret != pos) {
923                 perror("write seek");
924                 return 1;
925         }
926         gettimeofday(&tw1, NULL);
927         for (i = 0, buf = buf_alloc; i < _npages;
928              i += xfer, buf += xfer * PAGE_CACHE_SIZE / sizeof(int)) {
929                 rc = write(fd, buf, PAGE_CACHE_SIZE * xfer);
930                 if (rc != PAGE_CACHE_SIZE * xfer) {
931                         printf("write error (i %d, rc %d): %s\n", i, rc,
932                                strerror(errno));
933                         return(1);
934                 }
935         }
936         gettimeofday(&tw2, NULL);
937
938         memset(buf_alloc, 0, buf_size);
939
940         /* read */
941         ret = lseek(fd, pos, SEEK_SET);
942         if (ret != pos) {
943                 perror("read seek");
944                 return 1;
945         }
946         gettimeofday(&tr1, NULL);
947         for (i = 0, buf = buf_alloc; i < _npages;
948              i += xfer, buf += xfer * PAGE_CACHE_SIZE / sizeof(int)) {
949                 rc = read(fd, buf, PAGE_CACHE_SIZE * xfer);
950                 if (rc != PAGE_CACHE_SIZE * xfer) {
951                         printf("read error (i %d, rc %d): %s\n", i, rc,
952                                strerror(errno));
953                         return(1);
954                 }
955         }
956         gettimeofday(&tr2, NULL);
957
958         /* compute checksum */
959         for (i = 0, buf = buf_alloc; i < _npages; i++) {
960                 int sum = 0;
961                 for (j = 0; j < PAGE_CACHE_SIZE/sizeof(int); j++, buf++) {
962                         sum += *buf;
963                 }
964                 if (sum != check_sum[i]) {
965                         data_error = 1;
966                         printf("chunk %d checksum error expected %#x got %#x\n",
967                                 i, check_sum[i], sum);
968                 }
969         }
970
971         t_close(fd);
972         t_unlink(path);
973         tw = (tw2.tv_sec - tw1.tv_sec) * 1000000 + (tw2.tv_usec - tw1.tv_usec);
974         tr = (tr2.tv_sec - tr1.tv_sec) * 1000000 + (tr2.tv_usec - tr1.tv_usec);
975         printf(" (R:%.3fM/s, W:%.3fM/s)\n",
976                 (_npages * PAGE_CACHE_SIZE) / (tw / 1000000.0) / (1024 * 1024),
977                 (_npages * PAGE_CACHE_SIZE) / (tr / 1000000.0) / (1024 * 1024));
978
979         if (data_error)
980                 return 1;
981
982         return 0;
983 }
984
985 int t50(char *name)
986 {
987         int np = 1;
988         loff_t offset = 0;
989
990         ENTER("4k aligned i/o sanity");
991         while (np <= _npages) {
992                 printf("%3d per xfer(total %d)...\t", np, _npages);
993                 fflush(stdout);
994                 if (pages_io(np, offset) != 0)
995                         return 1;
996                 np += np;
997         }
998         LEAVE();
999 }
1000
1001 int t50b(char *name)
1002 {
1003         loff_t off_array[] = {1, 17, 255, 258, 4095, 4097, 8191,
1004                               1024*1024*1024*1024ULL};
1005         int i;
1006         long long offset;
1007
1008         ENTER("4k un-aligned i/o sanity");
1009         for (i = 0; i < sizeof(off_array)/sizeof(loff_t); i++) {
1010                 offset = off_array[i];
1011                 printf("16 per xfer(total %d), offset %10lld...\t",
1012                         _npages, offset);
1013                 if (pages_io(16, offset) != 0)
1014                         return 1;
1015         }
1016
1017         LEAVE();
1018 }
1019
1020 enum {
1021         T51_STEP = 42,
1022         T51_NR   = 1000
1023 };
1024
1025 /*
1026  * truncate(2) checks.
1027  */
1028 int t51(char *name)
1029 {
1030         char file[MAX_PATH_LENGTH] = "";
1031         int fd;
1032         long long size;
1033         int result;
1034
1035         ENTER("truncate() should truncate file to proper length");
1036         snprintf(file, MAX_PATH_LENGTH, "%s/test_t51_file", lustre_path);
1037
1038         for (size = 0; size < T51_NR * T51_STEP; size += T51_STEP) {
1039                 t_echo_create(file, "");
1040                 if (truncate(file, size) != 0) {
1041                         printf("\nerror truncating file: %s\n",strerror(errno));
1042                         return(-1);
1043                 }
1044                 result = check_file_size(file, size);
1045                 if (result != 0)
1046                         return result;
1047                 t_unlink(file);
1048
1049                 t_echo_create(file, "");
1050                 fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
1051                 if (fd < 0) {
1052                         printf("\nerror open file: %s\n", strerror(errno));
1053                         return(-1);
1054                 }
1055                 if (ftruncate(fd, size) != 0) {
1056                         printf("\nerror ftruncating file:%s\n",strerror(errno));
1057                         return(-1);
1058                 }
1059                 close(fd);
1060                 result = check_file_size(file, size);
1061                 if (result != 0)
1062                         return result;
1063                 t_unlink(file);
1064                 if (size % (T51_STEP * (T51_NR / 75)) == 0) {
1065                         printf(".");
1066                         fflush(stdout);
1067                 }
1068         }
1069         printf("\n");
1070         LEAVE();
1071 }
1072 /*
1073  * check atime update during read
1074  */
1075 int t52(char *name)
1076 {
1077         char file[MAX_PATH_LENGTH] = "";
1078         char buf[16];
1079         struct stat statbuf;
1080         time_t atime;
1081         time_t diff;
1082         int fd, i;
1083
1084         ENTER("atime should be updated during read");
1085         snprintf(file, MAX_PATH_LENGTH, "%s/test_t52_file", lustre_path);
1086
1087         t_echo_create(file, "check atime update during read");
1088         fd = open(file, O_RDONLY);
1089         if (fd < 0) {
1090                 printf("\nerror open file: %s\n", strerror(errno));
1091                 return(-1);
1092         }
1093         stat(file, &statbuf);
1094         printf("st_atime=%s", ctime(&statbuf.st_atime));
1095         atime = statbuf.st_atime;
1096         for (i = 0; i < 3; i++) {
1097                 ssize_t num_read;
1098                 sleep(2);
1099                 /* should not ignore read(2)'s return value */
1100                 num_read = read(fd, buf, sizeof(buf));
1101                 if (num_read < 0 ) {
1102                         printf("read from %s: %s\n", file, strerror(errno));
1103                         return -1;
1104                 }
1105                 stat(file, &statbuf);
1106                 printf("st_atime=%s", ctime(&statbuf.st_atime));
1107                 diff = statbuf.st_atime - atime;
1108                 if (diff <= 0) {
1109                         printf("atime doesn't updated! failed!\n");
1110                         close(fd);
1111                         t_unlink(file);
1112                         return -1;
1113                 }
1114                 atime = statbuf.st_atime;
1115         }
1116         close(fd);
1117         t_unlink(file);
1118         LEAVE();
1119 }
1120
1121 #define NEW_TIME        10000
1122 int t53(char *name)
1123 {
1124         char file[MAX_PATH_LENGTH] = "";
1125         struct utimbuf times;   /* struct. buffer for utime() */
1126         struct stat stat_buf;   /* struct buffer to hold file info. */
1127         time_t mtime, atime;
1128
1129         ENTER("mtime/atime should be updated by utime() call");
1130         snprintf(file, MAX_PATH_LENGTH, "%s/test_t53_file", lustre_path);
1131
1132         t_echo_create(file, "check mtime/atime update by utime() call");
1133
1134         /* Initialize the modification and access time in the times arg */
1135         times.actime = NEW_TIME+10;
1136         times.modtime = NEW_TIME;
1137
1138         /* file modification/access time */
1139         utime(file, &times);
1140
1141         if (stat(file, &stat_buf) < 0) {
1142                 printf("stat(2) of %s failed, error:%d %s\n",
1143                         file, errno, strerror(errno));
1144         }
1145         mtime = stat_buf.st_mtime;
1146         atime = stat_buf.st_atime;
1147
1148         if ((mtime == NEW_TIME) && (atime == NEW_TIME + 10)) {
1149                 t_unlink(file);
1150                 LEAVE();
1151         }
1152
1153         printf("mod time %ld, expected %ld\n", mtime, (long)NEW_TIME);
1154         printf("acc time %ld, expected %ld\n", atime, (long)NEW_TIME + 10);
1155
1156         t_unlink(file);
1157         return (-1);
1158 }
1159
1160 int t54(char *name)
1161 {
1162         char file[MAX_PATH_LENGTH] = "";
1163         struct flock lock;
1164         int fd, err;
1165
1166         ENTER("fcntl should return 0 when succeed in getting flock");
1167         snprintf(file, MAX_PATH_LENGTH, "%s/test_t54_file", lustre_path);
1168
1169         t_echo_create(file, "fcntl should return 0 when succeed");
1170
1171         fd = open(file, O_RDWR);
1172         if (fd < 0) {
1173                 printf("\nerror open file: %s\n", strerror(errno));
1174                 return(-1);
1175         }
1176         lock.l_type   = F_WRLCK;
1177         lock.l_start  = 0;
1178         lock.l_whence = 0;
1179         lock.l_len    = 1;
1180         if ((err = t_fcntl(fd, F_SETLKW, &lock)) != 0) {
1181                 fprintf(stderr, "fcntl returned: %d (%s)\n",
1182                         err, strerror(err));
1183                 close(fd);
1184                 t_unlink(file);
1185                 return (-1);
1186         }
1187
1188         lock.l_type   = F_UNLCK;
1189         t_fcntl(fd, F_SETLKW, &lock);
1190         close(fd);
1191         t_unlink(file);
1192         LEAVE();
1193 }
1194
1195 /* for O_DIRECTORY */
1196 #ifndef _GNU_SOURCE
1197 #define _GNU_SOURCE
1198 #endif
1199
1200 #define STRIPE_SIZE       (2048 * 2048)
1201 #define STRIPE_OFFSET           0
1202 #define STRIPE_COUNT            1
1203 int t55(char *name)
1204 {
1205         char path[MAX_PATH_LENGTH] = "";
1206         char file[MAX_PATH_LENGTH] = "";
1207         struct lov_user_md *lum = NULL;
1208         struct lov_user_ost_data *lo = NULL;
1209         int index, fd, buflen, rc;
1210
1211         ENTER("setstripe/getstripe");
1212         snprintf(path, MAX_PATH_LENGTH, "%s/test_t55", lustre_path);
1213         snprintf(file, MAX_PATH_LENGTH, "%s/test_t55/file_t55", lustre_path);
1214
1215         buflen = sizeof(struct lov_user_md);
1216         buflen += STRIPE_COUNT * sizeof(struct lov_user_ost_data);
1217         lum = (struct lov_user_md *)malloc(buflen);
1218         if (!lum) {
1219                 printf("out of memory!\n");
1220                 return -1;
1221         }
1222         memset(lum, 0, buflen);
1223
1224         t_mkdir(path);
1225         rc = llapi_file_create(path, STRIPE_SIZE, STRIPE_OFFSET,
1226                                STRIPE_COUNT, LOV_PATTERN_RAID0);
1227         if (rc) {
1228                 printf("llapi_file_create failed: rc = %d (%s) \n",
1229                        rc, strerror(-rc));
1230                 t_rmdir(path);
1231                 free(lum);
1232                 return -1;
1233         }
1234
1235         fd = open(file, O_CREAT | O_RDWR, 0644);
1236         if (fd < 0) {
1237                 printf("open file(%s) failed: rc = %d (%s) \n)",
1238                        file, fd, strerror(errno));
1239                 t_rmdir(path);
1240                 free(lum);
1241                 return -1;
1242         }
1243
1244         lum->lmm_magic = LOV_USER_MAGIC;
1245         lum->lmm_stripe_count = STRIPE_COUNT;
1246         rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, lum);
1247         if (rc) {
1248                 printf("dir:ioctl(LL_IOC_LOV_GETSTRIPE) failed: rc = %d(%s)\n",
1249                        rc, strerror(errno));
1250                 close(fd);
1251                 t_unlink(file);
1252                 t_rmdir(path);
1253                 free(lum);
1254                 return -1;
1255         }
1256
1257         close(fd);
1258
1259         if (opt_verbose) {
1260                 printf("lmm_magic:          0x%08X\n",  lum->lmm_magic);
1261                 printf("lmm_object_id:      "LPX64"\n",
1262                                                 lmm_oi_id(&lum->lmm_oi));
1263                 printf("lmm_object_seq:     "LPX64"\n",
1264                                                 lmm_oi_seq(&lum->lmm_oi));
1265                 printf("lmm_stripe_count:   %u\n", (int)lum->lmm_stripe_count);
1266                 printf("lmm_stripe_size:    %u\n",      lum->lmm_stripe_size);
1267                 printf("lmm_stripe_pattern: %x\n",      lum->lmm_pattern);
1268
1269                 for (index = 0; index < lum->lmm_stripe_count; index++) {
1270                         lo = lum->lmm_objects + index;
1271                         printf("object %d:\n", index);
1272                         printf("\tobject_oid:   "DOSTID"\n",
1273                                POSTID(&lo->l_ost_oi));
1274                         printf("\tost_gen:      %#x\n", lo->l_ost_gen);
1275                         printf("\tost_idx:      %u\n", lo->l_ost_idx);
1276                 }
1277         }
1278
1279         if (lum->lmm_magic != LOV_USER_MAGIC ||
1280             lum->lmm_pattern != LOV_PATTERN_RAID0 ||
1281             lum->lmm_stripe_size != STRIPE_SIZE ||
1282             lum->lmm_objects[0].l_ost_idx != STRIPE_OFFSET ||
1283             lum->lmm_stripe_count != STRIPE_COUNT) {
1284                 printf("incorrect striping information!\n");
1285                 t_unlink(file);
1286                 t_rmdir(path);
1287                 free(lum);
1288                 return -1;
1289         }
1290         t_unlink(file);
1291
1292         /* setstripe on regular file */
1293         rc = llapi_file_create(file, STRIPE_SIZE, STRIPE_OFFSET,
1294                                STRIPE_COUNT, LOV_PATTERN_RAID0);
1295         if (rc) {
1296                 printf("llapi_file_create failed: rc = %d (%s) \n",
1297                        rc, strerror(-rc));
1298                 t_unlink(file);
1299                 t_rmdir(path);
1300                 free(lum);
1301                 return -1;
1302         }
1303         fd = open(file, O_RDWR, 0644);
1304         if (fd < 0) {
1305                 printf("failed to open(%s): rc = %d (%s)\n",
1306                        file, fd, strerror(errno));
1307                 t_unlink(file);
1308                 t_rmdir(path);
1309                 free(lum);
1310                 return -1;
1311         }
1312
1313         lum->lmm_magic = LOV_USER_MAGIC;
1314         lum->lmm_stripe_count = STRIPE_COUNT;
1315         rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, lum);
1316         if (rc) {
1317                 printf("file:ioctl(LL_IOC_LOV_GETSTRIPE) failed: rc = %d(%s)\n",
1318                        rc, strerror(errno));
1319                 close(fd);
1320                 t_unlink(file);
1321                 t_rmdir(path);
1322                 free(lum);
1323                 return -1;
1324         }
1325         close(fd);
1326
1327         if (opt_verbose) {
1328                 printf("lmm_magic:          0x%08X\n",  lum->lmm_magic);
1329                 printf("lmm_object_id:      "LPX64"\n",
1330                                                 lmm_oi_id(&lum->lmm_oi));
1331                 printf("lmm_object_seq:     "LPX64"\n",
1332                                                 lmm_oi_seq(&lum->lmm_oi));
1333                 printf("lmm_stripe_count:   %u\n", (int)lum->lmm_stripe_count);
1334                 printf("lmm_stripe_size:    %u\n",      lum->lmm_stripe_size);
1335                 printf("lmm_stripe_pattern: %x\n",      lum->lmm_pattern);
1336
1337                 for (index = 0; index < lum->lmm_stripe_count; index++) {
1338                         lo = lum->lmm_objects + index;
1339                         printf("object %d:\n", index);
1340                         printf("\tobject_oid:   "DOSTID"\n",
1341                                POSTID(&lo->l_ost_oi));
1342                         printf("\tost_gen:      %#x\n", lo->l_ost_gen);
1343                         printf("\tost_idx:      %u\n", lo->l_ost_idx);
1344                 }
1345         }
1346
1347         if (lum->lmm_magic != LOV_USER_MAGIC ||
1348             lum->lmm_pattern != LOV_PATTERN_RAID0 ||
1349             lum->lmm_stripe_size != STRIPE_SIZE ||
1350             lum->lmm_objects[0].l_ost_idx != STRIPE_OFFSET ||
1351             lum->lmm_stripe_count != STRIPE_COUNT) {
1352                 printf("incorrect striping information!\n");
1353                 t_unlink(file);
1354                 t_rmdir(path);
1355                 free(lum);
1356                 return -1;
1357         }
1358
1359         t_unlink(file);
1360         t_rmdir(path);
1361         free(lum);
1362         LEAVE();
1363 }
1364
1365 /*
1366  * getdirentries should return -1 and set errno to EINVAL when the size
1367  * specified as an argument is too small to contain at least one entry
1368  * (see bugzilla ticket 12229)
1369  */
1370 int t56(char *name)
1371 {
1372         int fd;
1373         size_t nbytes;
1374         off_t basep = 0;
1375         long rc = 0;
1376         struct dirent64 dir;
1377
1378         ENTER("getdirentries should fail if nbytes is too small");
1379
1380         /* Set count to be very small.  The result should be EINVAL */
1381         nbytes = 8;
1382
1383         /* open the directory and call getdirentries */
1384         fd = t_opendir(lustre_path);
1385
1386         rc = getdirentries(fd, (char *)&dir, nbytes, &basep);
1387
1388         if (rc != -1) {
1389                 printf("Test failed: getdirentries returned %lld\n",
1390                        (long long)rc);
1391                 t_close(fd);
1392                 return -1;
1393         }
1394         if (errno != EINVAL) {
1395                 printf("Test failed: getdirentries returned %lld but errno is "
1396                        "set to %d (should be EINVAL)\n", (long long)rc, errno);
1397                 t_close(fd);
1398                 return -1;
1399         }
1400         t_close(fd);
1401
1402         LEAVE();
1403 }
1404
1405 extern void __liblustre_setup_(void);
1406 extern void __liblustre_cleanup_(void);
1407
1408
1409 void usage(char *cmd)
1410 {
1411         printf("\n"
1412              "usage: %s [-o test][-e test][-v] --target mgsnid:/fsname\n",
1413              cmd);
1414         printf("       %s --dumpfile dumpfile\n", cmd);
1415         exit(-1);
1416 }
1417
1418 struct testlist {
1419         int (*test)(char *name);
1420         char *name;
1421 } testlist[] = {
1422         { t1, "1" },
1423         { t2, "2" },
1424         { t3, "3" },
1425         { t4, "4" },
1426         { t6, "6" },
1427         { t6b, "6b" },
1428         { t7, "7" },
1429         { t8, "8" },
1430         { t9, "9" },
1431         { t10, "10" },
1432         { t11, "11" },
1433         { t12, "12" },
1434         { t13, "13" },
1435         { t14, "14" },
1436         { t15, "15" },
1437         { t16, "16" },
1438         { t17, "17" },
1439         { t18, "18" },
1440         { t18b, "t8b" },
1441         { t19, "19" },
1442         { t20, "20" },
1443         { t21, "21" },
1444         { t22, "22" },
1445         { t23, "23" },
1446         { t50, "50" },
1447         { t50b, "50b" },
1448         { t51, "51" },
1449         { t53, "53" },
1450         { t54, "54" },
1451         { t55, "55" },
1452         { t56, "56" },
1453         { NULL, NULL }
1454 };
1455
1456 int main(int argc, char * const argv[])
1457 {
1458         struct testlist *test;
1459         int opt_index, c, rc = 0, numonly = 0, numexcept = 0;
1460         char *only[100], *except[100];
1461         static struct option long_opts[] = {
1462                 {"dumpfile", 1, 0, 'd'},
1463                 {"only", 1, 0, 'o'},
1464                 {"except", 1, 0, 'e'},
1465                 {"target", 1, 0, 't'},
1466                 {"verbose", 1, 0, 'v'},
1467                 {0, 0, 0, 0}
1468         };
1469
1470         while ((c = getopt_long(argc, argv, "d:e:o:t:v", long_opts, &opt_index)) != -1) {
1471                 switch (c) {
1472                 case 'd':
1473                         setenv(ENV_LUSTRE_DUMPFILE, optarg, 1);
1474                         break;
1475                 case 'e':
1476                         if (numexcept == 0)
1477                                 printf("Not running test(s): ");
1478                         printf("%s ", optarg);
1479                         except[numexcept++] = optarg;
1480                         break;
1481                 case 'o':
1482                         if (numonly == 0)
1483                                 printf("Only running test(s): ");
1484                         printf("%s ", optarg);
1485                         only[numonly++] = optarg;
1486                         break;
1487                 case 't':
1488                         setenv(ENV_LUSTRE_MNTTGT, optarg, 1);
1489                         break;
1490                 case 'v':
1491                         opt_verbose++;
1492                         break;
1493                 default:
1494                         usage(argv[0]);
1495                         break;
1496                 }
1497         }
1498
1499         if (getenv(ENV_LUSTRE_MNTTGT) == NULL &&
1500             getenv(ENV_LUSTRE_DUMPFILE) == NULL)
1501                 usage(argv[0]);
1502
1503         if (optind != argc)
1504                 usage(argv[0]);
1505
1506         printf("\n");
1507
1508         __liblustre_setup_();
1509
1510         buf_size = _npages * PAGE_CACHE_SIZE;
1511         if (opt_verbose)
1512                 printf("allocating %d bytes buffer\n", buf_size);
1513         buf_alloc = calloc(1, buf_size);
1514         if (buf_alloc == NULL) {
1515                 fprintf(stderr, "error allocating %d\n", buf_size);
1516                 exit(-ENOMEM);
1517         }
1518
1519         for (test = testlist; test->test != NULL; test++) {
1520                 int run = 1, i;
1521                 int len, olen;
1522
1523                 if (numexcept > 0) {
1524                         len = strlen(test->name);
1525                         for (i = 0; i < numexcept; i++) {
1526                                 olen = strlen(except[i]);
1527
1528                                 if (len < olen)
1529                                         continue;
1530
1531                                 if (strncmp(except[i], test->name, olen) == 0) {
1532                                         switch(test->name[olen]) {
1533                                         case '0': case '1': case '2': case '3':
1534                                         case '4': case '5': case '6': case '7':
1535                                         case '8': case '9':
1536                                                 break;
1537                                         default:
1538                                                 run = 0;
1539                                                 break;
1540                                         }
1541                                 }
1542                         }
1543                 }
1544
1545                 if (numonly > 0) {
1546                         run = 0;
1547                         len = strlen(test->name);
1548                         for (i = 0; i < numonly; i++) {
1549                                 olen = strlen(only[i]);
1550
1551                                 if (len < olen)
1552                                         continue;
1553
1554                                 if (strncmp(only[i], test->name, olen) == 0) {
1555                                         switch(test->name[olen]) {
1556                                         case '0': case '1': case '2': case '3':
1557                                         case '4': case '5': case '6': case '7':
1558                                         case '8': case '9':
1559                                                 break;
1560                                         default:
1561                                                 run = 1;
1562                                                 break;
1563                                         }
1564                                 }
1565                         }
1566                 }
1567                 if (run && (rc = (test->test)(test->name)) != 0)
1568                         break;
1569         }
1570
1571         free(buf_alloc);
1572
1573         printf("liblustre is about to shutdown\n");
1574         __liblustre_cleanup_();
1575
1576         printf("complete successfully\n");
1577         return rc;
1578 }