Whamcloud - gitweb
070e3c69ba2734ff2750e2e66b958819d24da735
[fs/lustre-release.git] / lustre / liblustre / tests / sanity.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/liblustre/tests/sanity.c
37  *
38  * Lustre Light user test program
39  */
40
41 #define _BSD_SOURCE
42 #define _FILE_OFFSET_BITS 64
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <getopt.h>
48 #include <string.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <fcntl.h>
52 #include <signal.h>
53 #include <errno.h>
54 #include <dirent.h>
55 #include <sys/uio.h>
56 #include <sys/time.h>
57 #include <time.h>
58
59 #include <liblustre.h>
60 #include "test_common.h"
61 #include <lustre/liblustreapi.h>
62
63 #define _npages (2048)
64
65 void *buf_alloc;
66 int buf_size;
67 int opt_verbose;
68 struct timeval start;
69
70 extern char *lustre_path;
71
72 #define ENTER(str)                                                      \
73         do {                                                            \
74                 char buf[100];                                          \
75                 int len;                                                \
76                 gettimeofday(&start, NULL);                             \
77                 sprintf(buf, "===== START %s: %s %ld", __FUNCTION__,    \
78                         (str), (long)start.tv_sec);                     \
79                 len = strlen(buf);                                      \
80                 if (len < 79) {                                         \
81                         memset(buf+len, '=', 100-len);                  \
82                         buf[79] = '\n';                                 \
83                         buf[80] = 0;                                    \
84                 }                                                       \
85                 printf("%s", buf);                                      \
86         } while (0)
87
88 #define LEAVE()                                                         \
89         do {                                                            \
90                 struct timeval stop;                                    \
91                 char buf[100] = { '\0' };                               \
92                 int len = sizeof(buf) - 1;                              \
93                 long usec;                                              \
94                 gettimeofday(&stop, NULL);                              \
95                 usec = (stop.tv_sec - start.tv_sec) * 1000000 +         \
96                        (stop.tv_usec - start.tv_usec);                  \
97                 len = snprintf(buf, len,                                \
98                                "===== END TEST %s: successfully (%gs)", \
99                                __FUNCTION__, (double)usec / 1000000);   \
100                 if (len < 79) {                                         \
101                         memset(buf+len, '=', sizeof(buf) - len);        \
102                         buf[79] = '\n';                                 \
103                         buf[80] = 0;                                    \
104                 }                                                       \
105                 printf("%s", buf);                                      \
106                 return 0;                                               \
107         } while (0)
108
109 #define MAX_PATH_LENGTH 4096
110
111 int t1(char *name)
112 {
113         char path[MAX_PATH_LENGTH] = "";
114
115         ENTER("touch+unlink");
116         snprintf(path, MAX_PATH_LENGTH, "%s/test_t1", lustre_path);
117
118         if (opt_verbose)
119                 printf("touch+unlink %s\n", path);
120
121         t_touch(path);
122         t_unlink(path);
123         LEAVE();
124 }
125
126 int t2(char *name)
127 {
128         char path[MAX_PATH_LENGTH] = "";
129
130         ENTER("mkdir/rmdir");
131         snprintf(path, MAX_PATH_LENGTH, "%s/test_t2", lustre_path);
132
133         t_mkdir(path);
134         t_rmdir(path);
135         LEAVE();
136 }
137
138 int t3(char *name)
139 {
140         char path[MAX_PATH_LENGTH] = "";
141
142         ENTER("regular stat");
143         snprintf(path, MAX_PATH_LENGTH, "%s/test_t3", lustre_path);
144
145         t_touch(path);
146         t_check_stat(path, NULL);
147         t_unlink(path);
148         LEAVE();
149 }
150
151 int t4(char *name)
152 {
153         char path[MAX_PATH_LENGTH] = "";
154
155         ENTER("dir stat");
156         snprintf(path, MAX_PATH_LENGTH, "%s/test_t4", lustre_path);
157
158         t_mkdir(path);
159         t_check_stat(path, NULL);
160         t_rmdir(path);
161         LEAVE();
162 }
163
164 int t6(char *name)
165 {
166         char path[MAX_PATH_LENGTH] = "";
167         char path2[MAX_PATH_LENGTH] = "";
168
169         ENTER("symlink");
170         snprintf(path, MAX_PATH_LENGTH, "%s/test_t6", lustre_path);
171         snprintf(path2, MAX_PATH_LENGTH, "%s/test_t6_link", lustre_path);
172
173         t_touch(path);
174         t_symlink(path, path2);
175         t_check_stat(path2, NULL);
176         t_unlink(path2);
177         t_unlink(path);
178         LEAVE();
179 }
180
181 int t6b(char *name)
182 {
183         char path[MAX_PATH_LENGTH] = "";
184         char path2[MAX_PATH_LENGTH] = "";
185         char cwd[MAX_PATH_LENGTH] = "";
186         char *tmp;
187         int fd;
188
189         ENTER("symlink + chdir and open");
190         snprintf(path, MAX_PATH_LENGTH, "%s/test_t6b", lustre_path);
191         snprintf(path2, MAX_PATH_LENGTH, "%s/test_t6b_link", lustre_path);
192
193         t_mkdir(path);
194         t_symlink(path, path2);
195         t_check_stat(path2, NULL);
196
197         tmp = getcwd(cwd, MAX_PATH_LENGTH);
198         if (tmp == NULL) {
199                 fprintf(stderr, "current path too long to fit in "
200                         "MAX_PATH_LENGTH?\n");
201                 LEAVE();
202         }
203         t_chdir(path2);
204         t_chdir(cwd);
205         t_rmdir(path);
206         t_touch(path);
207
208         fd = t_open(path2);
209         t_close(fd);
210
211         t_unlink(path2);
212         t_unlink(path);
213         LEAVE();
214 }
215
216 int t7(char *name)
217 {
218         char path[MAX_PATH_LENGTH] = "";
219         int rc;
220
221         ENTER("mknod");
222         snprintf(path, MAX_PATH_LENGTH, "%s/test_t7", lustre_path);
223
224         if (geteuid() != 0) {
225                 rc = mknod(path, S_IFCHR | 0644, (5<<8 | 4));
226                 if (rc != -1 || errno != EPERM) {
227                         printf("mknod shouldn't success: rc %d, errno %d\n",
228                                 rc, errno);
229                 }
230         } else {
231                 t_mknod(path, S_IFCHR | 0644, 5, 4);
232                 t_check_stat(path, NULL);
233                 t_unlink(path);
234         }
235         LEAVE();
236 }
237
238 int t8(char *name)
239 {
240         char path[MAX_PATH_LENGTH] = "";
241
242         ENTER("chmod");
243         snprintf(path, MAX_PATH_LENGTH, "%s/test_t8", lustre_path);
244
245         /* Check file. */
246         t_touch(path);
247         t_chmod_raw(path, 0700);
248         t_check_stat(path, NULL);
249         t_unlink(path);
250
251         /* Check dir. */
252         t_mkdir(path);
253         t_chmod_raw(path, 0700);
254         t_check_stat(path, NULL);
255         t_rmdir(path);
256
257         LEAVE();
258 }
259
260 int t9(char *name)
261 {
262         char path[MAX_PATH_LENGTH] = "";
263         char path2[MAX_PATH_LENGTH] = "";
264
265         ENTER("hard link");
266         snprintf(path, MAX_PATH_LENGTH, "%s/test_t9", lustre_path);
267         snprintf(path2, MAX_PATH_LENGTH, "%s/test_t9_link", lustre_path);
268
269         t_touch(path);
270         t_link(path, path2);
271         t_check_stat(path, NULL);
272         t_check_stat(path2, NULL);
273         t_unlink(path);
274         t_unlink(path2);
275         LEAVE();
276 }
277
278 int t10(char *name)
279 {
280         char dir1[MAX_PATH_LENGTH] = "";
281         char dir2[MAX_PATH_LENGTH] = "";
282         char path1[MAX_PATH_LENGTH] = "";
283         char path2[MAX_PATH_LENGTH] = "";
284         char rename1[MAX_PATH_LENGTH] = "";
285         char rename2[MAX_PATH_LENGTH] = "";
286         char rename3[MAX_PATH_LENGTH] = "";
287
288         ENTER("rename");
289         snprintf(dir1, MAX_PATH_LENGTH, "%s/test_t10_dir1", lustre_path);
290         snprintf(dir2, MAX_PATH_LENGTH, "%s/test_t10_dir2", lustre_path);
291         snprintf(path1, MAX_PATH_LENGTH, "%s/test_t10_reg1", lustre_path);
292         snprintf(path2, MAX_PATH_LENGTH, "%s/test_t10_reg2", lustre_path);
293         snprintf(rename1, MAX_PATH_LENGTH, "%s/test_t10_dir1/rename1", lustre_path);
294         snprintf(rename2, MAX_PATH_LENGTH, "%s/test_t10_dir2/rename2", lustre_path);
295         snprintf(rename3, MAX_PATH_LENGTH, "%s/test_t10_dir2/rename3", lustre_path);
296
297         t_mkdir(dir1);
298         t_mkdir(dir2);
299         t_touch(path1);
300         t_touch(path2);
301         t_rename(path1, rename1);
302         t_rename(path2, rename2);
303         t_rename(rename1, rename2);
304         t_rename(dir1, rename3);
305         t_unlink(rename2);
306         t_rmdir(rename3);
307         t_rmdir(dir2);
308         LEAVE();
309 }
310
311 int t11(char *name)
312 {
313         char *base=lustre_path;
314         char path[MAX_PATH_LENGTH], path2[MAX_PATH_LENGTH];
315         int i, j, level = 5, nreg = 5;
316         ENTER("deep tree");
317
318         safe_strncpy(path, base, MAX_PATH_LENGTH);
319
320         for (i = 0; i < level; i++) {
321                 for (j = 0; j < nreg; j++) {
322                         sprintf(path2, "%s/file%d", path, j);
323                         t_touch(path2);
324                 }
325
326                 strcat(path, "/dir");
327                 t_mkdir(path);
328         }
329
330         for (i = level; i > 0; i--) {
331                 safe_strncpy(path, base, MAX_PATH_LENGTH);
332                 for (j = 1; j < i; j++)
333                         strcat(path, "/dir");
334
335                 for (j = 0; j < nreg; j++) {
336                         sprintf(path2, "%s/file%d", path, j);
337                         t_unlink(path2);
338                 }
339
340                 strcat(path, "/dir");
341                 t_rmdir(path);
342         }
343
344         LEAVE();
345 }
346
347 int t12(char *name)
348 {
349         char dir[MAX_PATH_LENGTH] = "";
350         char buf[1024*128];
351         int fd;
352         ENTER("empty directory readdir");
353         snprintf(dir, MAX_PATH_LENGTH, "%s/test_t12_dir", lustre_path);
354
355         t_mkdir(dir);
356         fd = t_opendir(dir);
357         t_ls(fd, buf, sizeof(buf));
358         t_close(fd);
359         t_rmdir(dir);
360         LEAVE();
361 }
362
363 int t13(char *name)
364 {
365         char dir[MAX_PATH_LENGTH] = "";
366         char path[1024];
367         char buf[1024];
368         const int nfiles = 20;
369         char *prefix = "test13_filename_prefix_";
370         int fd, i;
371         ENTER("multiple entries directory readdir");
372         snprintf(dir, MAX_PATH_LENGTH, "%s/test_t13_dir/", lustre_path);
373
374         t_mkdir(dir);
375         printf("Creating %d files...\n", nfiles);
376         for (i = 0; i < nfiles; i++) {
377                 sprintf(path, "%s%s%05d", dir, prefix, i);
378                 t_touch(path);
379         }
380         fd = t_opendir(dir);
381         t_ls(fd, buf, sizeof(buf));
382         t_close(fd);
383         printf("Cleanup...\n");
384         for (i = 0; i < nfiles; i++) {
385                 sprintf(path, "%s%s%05d", dir, prefix, i);
386                 t_unlink(path);
387         }
388         t_rmdir(dir);
389         LEAVE();
390 }
391
392 int t14(char *name)
393 {
394         char dir[MAX_PATH_LENGTH] = "";
395         char path[1024];
396         char buf[1024];
397         const int nfiles = 256;
398         char *prefix = "test14_filename_long_prefix_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA___";
399         cfs_dirent_t *ent;
400         int fd, i, rc, pos, index;
401         loff_t base = 0;
402         ENTER(">1 block(4k) directory readdir");
403         snprintf(dir, MAX_PATH_LENGTH, "%s/test_t14_dir/", lustre_path);
404
405         rc = mkdir(dir, 0755);
406         if (rc < 0 && errno != EEXIST) {
407                 printf("mkdir(%s) error: %s\n", dir, strerror(errno));
408                 exit(1);
409         }
410         printf("Creating %d files...\n", nfiles);
411         for (i = 0; i < nfiles; i++) {
412                 sprintf(path, "%s%s%05d", dir, prefix, i);
413                 t_touch(path);
414         }
415         fd = t_opendir(dir);
416         printf("Listing...\n");
417         index = 0;
418         while ((rc = getdirentries64(fd, buf, 1024, &base)) > 0) {
419                 pos = 0;
420                 while (pos < rc) {
421                         char *item;
422
423                         ent = (void *) buf + pos;
424                         item = (char *) ent->d_name;
425                         if (!strcmp(item, ".") || !strcmp(item, ".."))
426                                 goto iter;
427                         if (strstr(item, prefix) != item) {
428                                 printf("found bad name %s\n", item);
429                                 return(-1);
430                         }
431                         printf("[%03d]: %s\n",
432                                 index++, item + strlen(prefix));
433 iter:
434                         pos += ent->d_reclen;
435                 }
436         }
437         if (rc < 0) {
438                 printf("getdents error %d\n", rc);
439                 return(-1);
440         }
441         if (index != nfiles) {
442                 printf("get %d files != %d\n", index, nfiles);
443                 return(-1);
444         }
445         t_close(fd);
446         printf("Cleanup...\n");
447         for (i = 0; i < nfiles; i++) {
448                 sprintf(path, "%s%s%05d", dir, prefix, i);
449                 t_unlink(path);
450         }
451         t_rmdir(dir);
452         LEAVE();
453 }
454
455 int t15(char *name)
456 {
457         char file[MAX_PATH_LENGTH] = "";
458         int fd;
459         ENTER("open-stat-close");
460         snprintf(file, MAX_PATH_LENGTH, "%s/test_t15_file", lustre_path);
461
462         t_touch(file);
463         fd = t_open(file);
464         t_check_stat(file, NULL);
465         t_close(fd);
466         t_unlink(file);
467         LEAVE();
468 }
469
470 int t16(char *name)
471 {
472         char file[MAX_PATH_LENGTH] = "";
473         ENTER("small-write-read");
474         snprintf(file, MAX_PATH_LENGTH, "%s/test_t16_file", lustre_path);
475
476         t_echo_create(file, "aaaaaaaaaaaaaaaaaaaaaa");
477         t_grep(file, "aaaaaaaaaaaaaaaaaaaaaa");
478         t_unlink(file);
479         LEAVE();
480 }
481
482 int t17(char *name)
483 {
484         char file[MAX_PATH_LENGTH] = "";
485         int fd;
486         ENTER("open-unlink without close");
487         snprintf(file, MAX_PATH_LENGTH, "%s/test_t17_file", lustre_path);
488
489         fd = open(file, O_WRONLY | O_CREAT, 0666);
490         if (fd < 0) {
491                 printf("failed to create file: %s\n", strerror(errno));
492                 return(-1);
493         }
494         t_unlink(file);
495         LEAVE();
496 }
497
498 int t18(char *name)
499 {
500         char file[MAX_PATH_LENGTH] = "";
501         char buf[128];
502         int fd, i;
503         struct stat statbuf[3];
504         ENTER("write should change mtime/ctime");
505         snprintf(file, MAX_PATH_LENGTH, "%s/test_t18_file", lustre_path);
506
507         for (i = 0; i < 3; i++) {
508                 fd = open(file, O_RDWR|O_CREAT|O_APPEND, (mode_t)0666);
509                 if (fd < 0) {
510                         printf("error open file: %s\n", strerror(errno));
511                         return(-1);
512                 }
513                 if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
514                         printf("error write file\n");
515                         return(-1);
516                 }
517                 close(fd);
518                 if(stat(file, &statbuf[i]) != 0) {
519                         printf("Error stat\n");
520                         return(1);
521                 }
522                 printf("ctime %lu, mtime %lu\n",
523                         statbuf[i].st_ctime, statbuf[i].st_mtime);
524                 sleep(2);
525         }
526
527         for (i = 1; i < 3; i++) {
528                 if ((statbuf[i].st_ctime <= statbuf[i-1].st_ctime) ||
529                     (statbuf[i].st_mtime <= statbuf[i-1].st_mtime)) {
530                         printf("time error\n");
531                         return(-1);
532                 }
533         }
534         t_unlink(file);
535         LEAVE();
536 }
537
538 int t18b(char *name)
539 {
540         char file[MAX_PATH_LENGTH] = "";
541         int i;
542         struct stat statbuf[3];
543         ENTER("utime should change mtime/atime/ctime");
544         snprintf(file, MAX_PATH_LENGTH, "%s/test_t18b_file", lustre_path);
545         t_touch(file);
546
547         for (i = 0; i < 3; i++) {
548                 t_utime(file, NULL);
549                 if(stat(file, &statbuf[i]) != 0) {
550                         printf("Error stat\n");
551                         return(1);
552                 }
553                 printf("atime %lu, mtime %lu, ctime %lu\n",
554                        statbuf[i].st_atime, statbuf[i].st_mtime,
555                        statbuf[i].st_ctime);
556                 sleep(2);
557         }
558
559         for (i = 1; i < 3; i++) {
560                 if ((statbuf[i].st_atime <= statbuf[i-1].st_atime) ||
561                     (statbuf[i].st_mtime <= statbuf[i-1].st_mtime) ||
562                     (statbuf[i].st_ctime <= statbuf[i-1].st_ctime)) {
563                         printf("time error\n");
564                         return(-1);
565                 }
566         }
567         t_unlink(file);
568         LEAVE();
569 }
570
571 static int check_file_size(char *file, long long size)
572 {
573         struct stat statbuf;
574
575         if (stat(file, &statbuf) != 0) {
576                 printf("Error stat(%s)\n", file);
577                 return(1);
578         }
579         if (statbuf.st_size != size) {
580                 printf("size of %s: %lld != %lld\n", file,
581                        (long long)statbuf.st_size, size);
582                 return(-1);
583         }
584         return 0;
585 }
586
587 int t19(char *name)
588 {
589         char file[MAX_PATH_LENGTH] = "";
590         int fd;
591         int result;
592         ENTER("open(O_TRUNC) should truncate file to 0-length");
593         snprintf(file, MAX_PATH_LENGTH, "%s/test_t19_file", lustre_path);
594
595         t_echo_create(file, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
596
597         fd = open(file, O_RDWR|O_CREAT|O_TRUNC, (mode_t)0666);
598         if (fd < 0) {
599                 printf("error open file: %s\n", strerror(errno));
600                 return(-1);
601         }
602         close(fd);
603         result = check_file_size(file, 0);
604         if (result != 0)
605                 return result;
606         t_unlink(file);
607         LEAVE();
608 }
609
610 int t20(char *name)
611 {
612         char file[MAX_PATH_LENGTH] = "";
613         int fd;
614         struct iovec iov[2];
615         char buf[100];
616         ssize_t ret;
617         ENTER("trap app's general bad pointer for file i/o");
618         snprintf(file, MAX_PATH_LENGTH, "%s/test_t20_file", lustre_path);
619
620         fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
621         if (fd < 0) {
622                 printf("error open file: %s\n", strerror(errno));
623                 return(-1);
624         }
625
626         ret = write(fd, NULL, 20);
627         if (ret != -1 || errno != EFAULT) {
628                 printf("write 1: ret %lld, errno %d\n", (long long)ret, errno);
629                 return(1);
630         }
631         ret = write(fd, (void *)-1, 20);
632         if (ret != -1 || errno != EFAULT) {
633                 printf("write 2: ret %lld, errno %d\n", (long long)ret, errno);
634                 return(1);
635         }
636         iov[0].iov_base = NULL;
637         iov[0].iov_len = 10;
638         iov[1].iov_base = (void *)-1;
639         iov[1].iov_len = 10;
640         ret = writev(fd, iov, 2);
641         if (ret != -1 || errno != EFAULT) {
642                 printf("writev 1: ret %lld, errno %d\n", (long long)ret, errno);
643                 return(1);
644         }
645         iov[0].iov_base = NULL;
646         iov[0].iov_len = 0;
647         iov[1].iov_base = buf;
648         iov[1].iov_len = sizeof(buf);
649         ret = writev(fd, iov, 2);
650         if (ret != sizeof(buf)) {
651                 printf("writev 2: ret %lld, error %d\n", (long long)ret, errno);
652                 return(1);
653         }
654         lseek(fd, 0, SEEK_SET);
655
656         ret = read(fd, NULL, 20);
657         if (ret != -1 || errno != EFAULT) {
658                 printf("read 1: ret %lld, errno %d\n", (long long)ret, errno);
659                 return(1);
660         }
661         ret = read(fd, (void *)-1, 20);
662         if (ret != -1 || errno != EFAULT) {
663                 printf("read 2: ret %lld, error %d\n", (long long)ret, errno);
664                 return(1);
665         }
666         iov[0].iov_base = NULL;
667         iov[0].iov_len = 10;
668         iov[1].iov_base = (void *)-1;
669         iov[1].iov_len = 10;
670         ret = readv(fd, iov, 2);
671         if (ret != -1 || errno != EFAULT) {
672                 printf("readv 1: ret %lld, error %d\n", (long long)ret, errno);
673                 return(1);
674         }
675         iov[0].iov_base = NULL;
676         iov[0].iov_len = 0;
677         iov[1].iov_base = buf;
678         iov[1].iov_len = sizeof(buf);
679         ret = readv(fd, iov, 2);
680         if (ret != sizeof(buf)) {
681                 printf("readv 2: ret %lld, error %d\n", (long long)ret, errno);
682                 return(1);
683         }
684
685         close(fd);
686         t_unlink(file);
687         LEAVE();
688 }
689
690 int t21(char *name)
691 {
692         char file[MAX_PATH_LENGTH] = "";
693         int fd, ret;
694         struct flock lock = {
695                 .l_type = F_RDLCK,
696                 .l_whence = SEEK_SET,
697         };
698
699         ENTER("basic fcntl support");
700         snprintf(file, MAX_PATH_LENGTH, "%s/test_t21_file", lustre_path);
701
702         fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
703         if (fd < 0) {
704                 printf("error open file: %s\n", file);
705                 return(-1);
706         }
707
708         t_fcntl(fd, F_SETFL, O_APPEND);
709         if (!(ret = t_fcntl(fd, F_GETFL)) & O_APPEND) {
710                 printf("error get flag: ret %x\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         ssize_t 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_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         off_t ret;
796         off_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, 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, 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                 sleep(2);
1096                 read(fd, buf, sizeof(buf));
1097                 stat(file, &statbuf);
1098                 printf("st_atime=%s", ctime(&statbuf.st_atime));
1099                 diff = statbuf.st_atime - atime;
1100                 if (diff <= 0) {
1101                         printf("atime doesn't updated! failed!\n");
1102                         close(fd);
1103                         t_unlink(file);
1104                         return -1;
1105                 }
1106                 atime = statbuf.st_atime;
1107         }
1108         close(fd);
1109         t_unlink(file);
1110         LEAVE();
1111 }
1112
1113 #define NEW_TIME        10000
1114 int t53(char *name)
1115 {
1116         char file[MAX_PATH_LENGTH] = "";
1117         struct utimbuf times;   /* struct. buffer for utime() */
1118         struct stat stat_buf;   /* struct buffer to hold file info. */
1119         time_t mtime, atime;
1120
1121         ENTER("mtime/atime should be updated by utime() call");
1122         snprintf(file, MAX_PATH_LENGTH, "%s/test_t53_file", lustre_path);
1123
1124         t_echo_create(file, "check mtime/atime update by utime() call");
1125
1126         /* Initialize the modification and access time in the times arg */
1127         times.actime = NEW_TIME+10;
1128         times.modtime = NEW_TIME;
1129
1130         /* file modification/access time */
1131         utime(file, &times);
1132
1133         if (stat(file, &stat_buf) < 0) {
1134                 printf("stat(2) of %s failed, error:%d %s\n",
1135                         file, errno, strerror(errno));
1136         }
1137         mtime = stat_buf.st_mtime;
1138         atime = stat_buf.st_atime;
1139
1140         if ((mtime == NEW_TIME) && (atime == NEW_TIME + 10)) {
1141                 t_unlink(file);
1142                 LEAVE();
1143         }
1144
1145         printf("mod time %ld, expected %ld\n", mtime, (long)NEW_TIME);
1146         printf("acc time %ld, expected %ld\n", atime, (long)NEW_TIME + 10);
1147
1148         t_unlink(file);
1149         return (-1);
1150 }
1151
1152 int t54(char *name)
1153 {
1154         char file[MAX_PATH_LENGTH] = "";
1155         struct flock lock;
1156         int fd, err;
1157
1158         ENTER("fcntl should return 0 when succeed in getting flock");
1159         snprintf(file, MAX_PATH_LENGTH, "%s/test_t54_file", lustre_path);
1160
1161         t_echo_create(file, "fcntl should return 0 when succeed");
1162
1163         fd = open(file, O_RDWR);
1164         if (fd < 0) {
1165                 printf("\nerror open file: %s\n", strerror(errno));
1166                 return(-1);
1167         }
1168         lock.l_type   = F_WRLCK;
1169         lock.l_start  = 0;
1170         lock.l_whence = 0;
1171         lock.l_len    = 1;
1172         if ((err = t_fcntl(fd, F_SETLKW, &lock)) != 0) {
1173                 fprintf(stderr, "fcntl returned: %d (%s)\n",
1174                         err, strerror(err));
1175                 close(fd);
1176                 t_unlink(file);
1177                 return (-1);
1178         }
1179
1180         lock.l_type   = F_UNLCK;
1181         t_fcntl(fd, F_SETLKW, &lock);
1182         close(fd);
1183         t_unlink(file);
1184         LEAVE();
1185 }
1186
1187 /* for O_DIRECTORY */
1188 #ifndef _GNU_SOURCE
1189 #define _GNU_SOURCE
1190 #endif
1191
1192 #define STRIPE_SIZE       (2048 * 2048)
1193 #define STRIPE_OFFSET           0
1194 #define STRIPE_COUNT            1
1195 int t55(char *name)
1196 {
1197         char path[MAX_PATH_LENGTH] = "";
1198         char file[MAX_PATH_LENGTH] = "";
1199         struct lov_user_md *lum = NULL;
1200         struct lov_user_ost_data *lo = NULL;
1201         int index, fd, buflen, rc;
1202
1203         ENTER("setstripe/getstripe");
1204         snprintf(path, MAX_PATH_LENGTH, "%s/test_t55", lustre_path);
1205         snprintf(file, MAX_PATH_LENGTH, "%s/test_t55/file_t55", lustre_path);
1206
1207         buflen = sizeof(struct lov_user_md);
1208         buflen += STRIPE_COUNT * sizeof(struct lov_user_ost_data);
1209         lum = (struct lov_user_md *)malloc(buflen);
1210         if (!lum) {
1211                 printf("out of memory!\n");
1212                 return -1;
1213         }
1214         memset(lum, 0, buflen);
1215
1216         t_mkdir(path);
1217         rc = llapi_file_create(path, STRIPE_SIZE, STRIPE_OFFSET,
1218                                STRIPE_COUNT, LOV_PATTERN_RAID0);
1219         if (rc) {
1220                 printf("llapi_file_create failed: rc = %d (%s) \n",
1221                        rc, strerror(-rc));
1222                 t_rmdir(path);
1223                 free(lum);
1224                 return -1;
1225         }
1226
1227         fd = open(file, O_CREAT | O_RDWR, 0644);
1228         if (fd < 0) {
1229                 printf("open file(%s) failed: rc = %d (%s) \n)",
1230                        file, fd, strerror(errno));
1231                 t_rmdir(path);
1232                 free(lum);
1233                 return -1;
1234         }
1235
1236         lum->lmm_magic = LOV_USER_MAGIC;
1237         lum->lmm_stripe_count = STRIPE_COUNT;
1238         rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, lum);
1239         if (rc) {
1240                 printf("dir:ioctl(LL_IOC_LOV_GETSTRIPE) failed: rc = %d(%s)\n",
1241                        rc, strerror(errno));
1242                 close(fd);
1243                 t_unlink(file);
1244                 t_rmdir(path);
1245                 free(lum);
1246                 return -1;
1247         }
1248
1249         close(fd);
1250
1251         if (opt_verbose) {
1252                 printf("lmm_magic:          0x%08X\n",  lum->lmm_magic);
1253                 printf("lmm_object_id:      "LPX64"\n", lum->lmm_object_id);
1254                 printf("lmm_object_gr:      "LPX64"\n", lum->lmm_object_gr);
1255                 printf("lmm_stripe_count:   %u\n", (int)lum->lmm_stripe_count);
1256                 printf("lmm_stripe_size:    %u\n",      lum->lmm_stripe_size);
1257                 printf("lmm_stripe_pattern: %x\n",      lum->lmm_pattern);
1258
1259                 for (index = 0; index < lum->lmm_stripe_count; index++) {
1260                         lo = lum->lmm_objects + index;
1261                         printf("object %d:\n", index);
1262                         printf("\tobject_gr:    "LPX64"\n", lo->l_object_gr);
1263                         printf("\tobject_id:    "LPX64"\n", lo->l_object_id);
1264                         printf("\tost_gen:      %#x\n", lo->l_ost_gen);
1265                         printf("\tost_idx:      %u\n", lo->l_ost_idx);
1266                 }
1267         }
1268
1269         if (lum->lmm_magic != LOV_USER_MAGIC ||
1270             lum->lmm_pattern != LOV_PATTERN_RAID0 ||
1271             lum->lmm_stripe_size != STRIPE_SIZE ||
1272             lum->lmm_objects[0].l_ost_idx != STRIPE_OFFSET ||
1273             lum->lmm_stripe_count != STRIPE_COUNT) {
1274                 printf("incorrect striping information!\n");
1275                 t_unlink(file);
1276                 t_rmdir(path);
1277                 free(lum);
1278                 return -1;
1279         }
1280         t_unlink(file);
1281
1282         /* setstripe on regular file */
1283         rc = llapi_file_create(file, STRIPE_SIZE, STRIPE_OFFSET,
1284                                STRIPE_COUNT, LOV_PATTERN_RAID0);
1285         if (rc) {
1286                 printf("llapi_file_create failed: rc = %d (%s) \n",
1287                        rc, strerror(-rc));
1288                 t_unlink(file);
1289                 t_rmdir(path);
1290                 free(lum);
1291                 return -1;
1292         }
1293         fd = open(file, O_RDWR, 0644);
1294         if (fd < 0) {
1295                 printf("failed to open(%s): rc = %d (%s)\n",
1296                        file, fd, strerror(errno));
1297                 t_unlink(file);
1298                 t_rmdir(path);
1299                 free(lum);
1300                 return -1;
1301         }
1302
1303         lum->lmm_magic = LOV_USER_MAGIC;
1304         lum->lmm_stripe_count = STRIPE_COUNT;
1305         rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, lum);
1306         if (rc) {
1307                 printf("file:ioctl(LL_IOC_LOV_GETSTRIPE) failed: rc = %d(%s)\n",
1308                        rc, strerror(errno));
1309                 close(fd);
1310                 t_unlink(file);
1311                 t_rmdir(path);
1312                 free(lum);
1313                 return -1;
1314         }
1315         close(fd);
1316
1317         if (opt_verbose) {
1318                 printf("lmm_magic:          0x%08X\n",  lum->lmm_magic);
1319                 printf("lmm_object_id:      "LPX64"\n", lum->lmm_object_id);
1320                 printf("lmm_object_gr:      "LPX64"\n", lum->lmm_object_gr);
1321                 printf("lmm_stripe_count:   %u\n", (int)lum->lmm_stripe_count);
1322                 printf("lmm_stripe_size:    %u\n",      lum->lmm_stripe_size);
1323                 printf("lmm_stripe_pattern: %x\n",      lum->lmm_pattern);
1324
1325                 for (index = 0; index < lum->lmm_stripe_count; index++) {
1326                         lo = lum->lmm_objects + index;
1327                         printf("object %d:\n", index);
1328                         printf("\tobject_gr:    "LPX64"\n", lo->l_object_gr);
1329                         printf("\tobject_id:    "LPX64"\n", lo->l_object_id);
1330                         printf("\tost_gen:      %#x\n", lo->l_ost_gen);
1331                         printf("\tost_idx:      %u\n", lo->l_ost_idx);
1332                 }
1333         }
1334
1335         if (lum->lmm_magic != LOV_USER_MAGIC ||
1336             lum->lmm_pattern != LOV_PATTERN_RAID0 ||
1337             lum->lmm_stripe_size != STRIPE_SIZE ||
1338             lum->lmm_objects[0].l_ost_idx != STRIPE_OFFSET ||
1339             lum->lmm_stripe_count != STRIPE_COUNT) {
1340                 printf("incorrect striping information!\n");
1341                 t_unlink(file);
1342                 t_rmdir(path);
1343                 free(lum);
1344                 return -1;
1345         }
1346
1347         t_unlink(file);
1348         t_rmdir(path);
1349         free(lum);
1350         LEAVE();
1351 }
1352
1353 /*
1354  * getdirentries should return -1 and set errno to EINVAL when the size
1355  * specified as an argument is too small to contain at least one entry
1356  * (see bugzilla ticket 12229)
1357  */
1358 int t56(char *name)
1359 {
1360         int fd;
1361         size_t nbytes;
1362         off_t basep = 0;
1363         ssize_t rc = 0;
1364         cfs_dirent_t dir;
1365
1366         ENTER("getdirentries should fail if nbytes is too small");
1367
1368         /* Set count to be very small.  The result should be EINVAL */
1369         nbytes = 8;
1370
1371         /* open the directory and call getdirentries */
1372         fd = t_opendir(lustre_path);
1373
1374         rc = getdirentries(fd, (char *)&dir, nbytes, &basep);
1375
1376         if (rc != -1) {
1377                 printf("Test failed: getdirentries returned %lld\n",
1378                        (long long)rc);
1379                 t_close(fd);
1380                 return -1;
1381         }
1382         if (errno != EINVAL) {
1383                 printf("Test failed: getdirentries returned %lld but errno is "
1384                        "set to %d (should be EINVAL)\n", (long long)rc, errno);
1385                 t_close(fd);
1386                 return -1;
1387         }
1388         t_close(fd);
1389
1390         LEAVE();
1391 }
1392
1393 extern void __liblustre_setup_(void);
1394 extern void __liblustre_cleanup_(void);
1395
1396
1397 void usage(char *cmd)
1398 {
1399         printf("\n"
1400              "usage: %s [-o test][-e test][-v] --target mgsnid:/fsname\n",
1401              cmd);
1402         printf("       %s --dumpfile dumpfile\n", cmd);
1403         exit(-1);
1404 }
1405
1406 struct testlist {
1407         int (*test)(char *name);
1408         char *name;
1409 } testlist[] = {
1410         { t1, "1" },
1411         { t2, "2" },
1412         { t3, "3" },
1413         { t4, "4" },
1414         { t6, "6" },
1415         { t6b, "6b" },
1416         { t7, "7" },
1417         { t8, "8" },
1418         { t9, "9" },
1419         { t10, "10" },
1420         { t11, "11" },
1421         { t12, "12" },
1422         { t13, "13" },
1423         { t14, "14" },
1424         { t15, "15" },
1425         { t16, "16" },
1426         { t17, "17" },
1427         { t18, "18" },
1428         { t18b, "t8b" },
1429         { t19, "19" },
1430         { t20, "20" },
1431         { t21, "21" },
1432         { t22, "22" },
1433         { t23, "23" },
1434         { t50, "50" },
1435         { t50b, "50b" },
1436         { t51, "51" },
1437         { t53, "53" },
1438         { t54, "54" },
1439         { t55, "55" },
1440         { t56, "56" },
1441         { NULL, NULL }
1442 };
1443
1444 int main(int argc, char * const argv[])
1445 {
1446         struct testlist *test;
1447         int opt_index, c, rc = 0, numonly = 0, numexcept = 0;
1448         char *only[100], *except[100];
1449         static struct option long_opts[] = {
1450                 {"dumpfile", 1, 0, 'd'},
1451                 {"only", 1, 0, 'o'},
1452                 {"except", 1, 0, 'e'},
1453                 {"target", 1, 0, 't'},
1454                 {"verbose", 1, 0, 'v'},
1455                 {0, 0, 0, 0}
1456         };
1457
1458         while ((c = getopt_long(argc, argv, "d:e:o:t:v", long_opts, &opt_index)) != -1) {
1459                 switch (c) {
1460                 case 'd':
1461                         setenv(ENV_LUSTRE_DUMPFILE, optarg, 1);
1462                         break;
1463                 case 'e':
1464                         if (numexcept == 0)
1465                                 printf("Not running test(s): ");
1466                         printf("%s ", optarg);
1467                         except[numexcept++] = optarg;
1468                         break;
1469                 case 'o':
1470                         if (numonly == 0)
1471                                 printf("Only running test(s): ");
1472                         printf("%s ", optarg);
1473                         only[numonly++] = optarg;
1474                         break;
1475                 case 't':
1476                         setenv(ENV_LUSTRE_MNTTGT, optarg, 1);
1477                         break;
1478                 case 'v':
1479                         opt_verbose++;
1480                         break;
1481                 default:
1482                         usage(argv[0]);
1483                         break;
1484                 }
1485         }
1486
1487         if (getenv(ENV_LUSTRE_MNTTGT) == NULL &&
1488             getenv(ENV_LUSTRE_DUMPFILE) == NULL)
1489                 usage(argv[0]);
1490
1491         if (optind != argc)
1492                 usage(argv[0]);
1493
1494         printf("\n");
1495
1496         __liblustre_setup_();
1497
1498         buf_size = _npages * CFS_PAGE_SIZE;
1499         if (opt_verbose)
1500                 printf("allocating %d bytes buffer\n", buf_size);
1501         buf_alloc = calloc(1, buf_size);
1502         if (buf_alloc == NULL) {
1503                 fprintf(stderr, "error allocating %d\n", buf_size);
1504                 exit(-ENOMEM);
1505         }
1506
1507         for (test = testlist; test->test != NULL; test++) {
1508                 int run = 1, i;
1509                 int len, olen;
1510
1511                 if (numexcept > 0) {
1512                         len = strlen(test->name);
1513                         for (i = 0; i < numexcept; i++) {
1514                                 olen = strlen(except[i]);
1515
1516                                 if (len < olen)
1517                                         continue;
1518
1519                                 if (strncmp(except[i], test->name, olen) == 0) {
1520                                         switch(test->name[olen]) {
1521                                         case '0': case '1': case '2': case '3':
1522                                         case '4': case '5': case '6': case '7':
1523                                         case '8': case '9':
1524                                                 break;
1525                                         default:
1526                                                 run = 0;
1527                                                 break;
1528                                         }
1529                                 }
1530                         }
1531                 }
1532
1533                 if (numonly > 0) {
1534                         run = 0;
1535                         len = strlen(test->name);
1536                         for (i = 0; i < numonly; i++) {
1537                                 olen = strlen(only[i]);
1538
1539                                 if (len < olen)
1540                                         continue;
1541
1542                                 if (strncmp(only[i], test->name, olen) == 0) {
1543                                         switch(test->name[olen]) {
1544                                         case '0': case '1': case '2': case '3':
1545                                         case '4': case '5': case '6': case '7':
1546                                         case '8': case '9':
1547                                                 break;
1548                                         default:
1549                                                 run = 1;
1550                                                 break;
1551                                         }
1552                                 }
1553                         }
1554                 }
1555                 if (run && (rc = (test->test)(test->name)) != 0)
1556                         break;
1557         }
1558
1559         free(buf_alloc);
1560
1561         printf("liblustre is about to shutdown\n");
1562         __liblustre_cleanup_();
1563
1564         printf("complete successfully\n");
1565         return rc;
1566 }