Whamcloud - gitweb
fce471c0aa1a6ec5c13e6842032399ce34df80ba
[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  * Lustre Light user test program
5  *
6  *  Copyright (c) 2002, 2003 Cluster File Systems, Inc.
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #define _BSD_SOURCE
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <getopt.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <sys/queue.h>
35 #include <signal.h>
36 #include <errno.h>
37 #include <dirent.h>
38 #include <sys/uio.h>
39 #include <sys/time.h>
40
41 #include "test_common.h"
42
43 extern char *lustre_path;
44
45 #define ENTRY(str)                                                      \
46         do {                                                            \
47                 char buf[100];                                          \
48                 int len;                                                \
49                 sprintf(buf, "===== START: %s ", (str));                \
50                 len = strlen(buf);                                      \
51                 if (len < 79) {                                         \
52                         memset(buf+len, '=', 100-len);                  \
53                         buf[79] = '\n';                                 \
54                         buf[80] = 0;                                    \
55                 }                                                       \
56                 printf("%s", buf);                                      \
57         } while (0)
58
59 #define LEAVE()                                                         \
60         do {                                                            \
61                 printf("----- END TEST successfully ---");              \
62                 printf("-----------------------------");                \
63                 printf("-------------------\n");                        \
64         } while (0)
65
66 #define MAX_PATH_LENGTH 4096
67
68 void t1()
69 {
70         char path[MAX_PATH_LENGTH] = "";
71
72         ENTRY("create/delete");
73         snprintf(path, MAX_PATH_LENGTH, "%s/test_t1", lustre_path);
74
75         t_touch(path);
76         t_unlink(path);
77         LEAVE();
78 }
79
80 void t2()
81 {
82         char path[MAX_PATH_LENGTH] = "";
83
84         ENTRY("mkdir/rmdir");
85         snprintf(path, MAX_PATH_LENGTH, "%s/test_t2", lustre_path);
86
87         t_mkdir(path);
88         t_rmdir(path);
89         LEAVE();
90 }
91
92 void t3()
93 {
94         char path[MAX_PATH_LENGTH] = "";
95
96         ENTRY("regular stat");
97         snprintf(path, MAX_PATH_LENGTH, "%s/test_t3", lustre_path);
98
99         t_touch(path);
100         t_check_stat(path, NULL);
101         t_unlink(path);
102         LEAVE();
103 }
104
105 void t4()
106 {
107         char path[MAX_PATH_LENGTH] = "";
108
109         ENTRY("dir stat");
110         snprintf(path, MAX_PATH_LENGTH, "%s/test_t4", lustre_path);
111
112         t_mkdir(path);
113         t_check_stat(path, NULL);
114         t_rmdir(path);
115         LEAVE();
116 }
117
118 void t6()
119 {
120         char path[MAX_PATH_LENGTH] = "";
121         char path2[MAX_PATH_LENGTH] = "";
122
123         ENTRY("symlink");
124         snprintf(path, MAX_PATH_LENGTH, "%s/test_t6", lustre_path);
125         snprintf(path2, MAX_PATH_LENGTH, "%s/test_t6_link", lustre_path);
126
127         t_touch(path);
128         t_symlink(path, path2);
129         t_check_stat(path2, NULL);
130         t_unlink(path2);
131         t_unlink(path);
132         LEAVE();
133 }
134
135 void t7()
136 {
137         char path[MAX_PATH_LENGTH] = "";
138         int rc;
139
140         ENTRY("mknod");
141         snprintf(path, MAX_PATH_LENGTH, "%s/test_t7", lustre_path);
142
143         if (geteuid() != 0) {
144                 rc = mknod(path, S_IFCHR | 0644, (5<<8 | 4));
145                 if (rc != -1 || errno != EPERM) {
146                         printf("mknod shouldn't success: rc %d, errno %d\n",
147                                 rc, errno);
148                 }
149         } else {
150                 t_mknod(path, S_IFCHR | 0644, 5, 4);
151                 t_check_stat(path, NULL);
152                 t_unlink(path);
153         }
154         LEAVE();
155 }
156
157 void t8()
158 {
159         char path[MAX_PATH_LENGTH] = "";
160
161         ENTRY("chmod");
162         snprintf(path, MAX_PATH_LENGTH, "%s/test_t8", lustre_path);
163
164         t_touch(path);
165         t_chmod_raw(path, 0700);
166         t_check_stat(path, NULL);
167         t_unlink(path);
168         LEAVE();
169 }
170
171 void t9()
172 {
173         char path[MAX_PATH_LENGTH] = "";
174         char path2[MAX_PATH_LENGTH] = "";
175
176         ENTRY("hard link");
177         snprintf(path, MAX_PATH_LENGTH, "%s/test_t9", lustre_path);
178         snprintf(path2, MAX_PATH_LENGTH, "%s/test_t9_link", lustre_path);
179
180         t_touch(path);
181         t_link(path, path2);
182         t_check_stat(path, NULL);
183         t_check_stat(path2, NULL);
184         t_unlink(path);
185         t_unlink(path2);
186         LEAVE();
187 }
188
189 void t10()
190 {
191         char dir1[MAX_PATH_LENGTH] = "";
192         char dir2[MAX_PATH_LENGTH] = "";
193         char path1[MAX_PATH_LENGTH] = "";
194         char path2[MAX_PATH_LENGTH] = "";
195         char rename1[MAX_PATH_LENGTH] = "";
196         char rename2[MAX_PATH_LENGTH] = "";
197         char rename3[MAX_PATH_LENGTH] = "";
198
199         ENTRY("rename");
200         snprintf(dir1, MAX_PATH_LENGTH, "%s/test_t10_dir1", lustre_path);
201         snprintf(dir2, MAX_PATH_LENGTH, "%s/test_t10_dir2", lustre_path);
202         snprintf(path1, MAX_PATH_LENGTH, "%s/test_t10_reg1", lustre_path);
203         snprintf(path2, MAX_PATH_LENGTH, "%s/test_t10_reg2", lustre_path);
204         snprintf(rename1, MAX_PATH_LENGTH, "%s/test_t10_dir1/rename1", lustre_path);
205         snprintf(rename2, MAX_PATH_LENGTH, "%s/test_t10_dir2/rename2", lustre_path);
206         snprintf(rename3, MAX_PATH_LENGTH, "%s/test_t10_dir2/rename3", lustre_path);
207
208         t_mkdir(dir1);
209         t_mkdir(dir2);
210         t_touch(path1);
211         t_touch(path2);
212         t_rename(path1, rename1);
213         t_rename(path2, rename2);
214         t_rename(rename1, rename2);
215         t_rename(dir1, rename3);
216         t_unlink(rename2);
217         t_rmdir(rename3);
218         t_rmdir(dir2);
219         LEAVE();
220 }
221
222 void t11()
223 {
224         char *base=lustre_path;
225         char path[MAX_PATH_LENGTH], path2[MAX_PATH_LENGTH];
226         int i, j, level = 5, nreg = 5;
227         ENTRY("deep tree");
228
229         safe_strncpy(path, base, MAX_PATH_LENGTH);
230
231         for (i = 0; i < level; i++) {
232                 for (j = 0; j < nreg; j++) {
233                         sprintf(path2, "%s/file%d", path, j);
234                         t_touch(path2);
235                 }
236
237                 strcat(path, "/dir");
238                 t_mkdir(path);
239         }
240
241         for (i = level; i > 0; i--) {
242                 safe_strncpy(path, base, MAX_PATH_LENGTH);
243                 for (j = 1; j < i; j++)
244                         strcat(path, "/dir");
245                 
246                 for (j = 0; j < nreg; j++) {
247                         sprintf(path2, "%s/file%d", path, j);
248                         t_unlink(path2);
249                 }
250
251                 strcat(path, "/dir");
252                 t_rmdir(path);
253         }
254
255         LEAVE();
256 }
257
258 void t12()
259 {
260         char dir[MAX_PATH_LENGTH] = "";
261         char buf[1024*128];
262         int fd;
263         ENTRY("empty directory readdir");
264         snprintf(dir, MAX_PATH_LENGTH, "%s/test_t12_dir", lustre_path);
265
266         t_mkdir(dir);
267         fd = t_opendir(dir);
268         t_ls(fd, buf, sizeof(buf));
269         t_close(fd);
270         t_rmdir(dir);
271         LEAVE();
272 }
273
274 void t13()
275 {
276         char dir[MAX_PATH_LENGTH] = "";
277         char name[1024];
278         char buf[1024];
279         const int nfiles = 20;
280         char *prefix = "test13_filename_prefix_";
281         int fd, i;
282         ENTRY("multiple entries directory readdir");
283         snprintf(dir, MAX_PATH_LENGTH, "%s/test_t13_dir/", lustre_path);
284
285         t_mkdir(dir);
286         printf("Creating %d files...\n", nfiles);
287         for (i = 0; i < nfiles; i++) {
288                 sprintf(name, "%s%s%05d", dir, prefix, i);
289                 t_touch(name);
290         }
291         fd = t_opendir(dir);
292         t_ls(fd, buf, sizeof(buf));
293         t_close(fd);
294         printf("Cleanup...\n");
295         for (i = 0; i < nfiles; i++) {
296                 sprintf(name, "%s%s%05d", dir, prefix, i);
297                 t_unlink(name);
298         }
299         t_rmdir(dir);
300         LEAVE();
301 }
302
303 void t14()
304 {
305         char dir[MAX_PATH_LENGTH] = "";
306         char name[1024];
307         char buf[1024];
308         const int nfiles = 256;
309         char *prefix = "test14_filename_long_prefix_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA___";
310         struct dirent64 *ent;
311         int fd, i, rc, pos, index;
312         loff_t base = 0;
313         ENTRY(">1 block(4k) directory readdir");
314         snprintf(dir, MAX_PATH_LENGTH, "%s/test_t14_dir/", lustre_path);
315
316         t_mkdir(dir);
317         printf("Creating %d files...\n", nfiles);
318         for (i = 0; i < nfiles; i++) {
319                 sprintf(name, "%s%s%05d", dir, prefix, i);
320                 t_touch(name);
321         }
322         fd = t_opendir(dir);
323         printf("Listing...\n");
324         index = 0;
325         while ((rc = getdirentries64(fd, buf, 1024, &base)) > 0) {
326                 pos = 0;
327                 while (pos < rc) {
328                         char *item;
329
330                         ent = (struct dirent64 *) ((char*) buf + pos);
331                         item = (char *) ent->d_name;
332                         if (!strcmp(item, ".") || !strcmp(item, ".."))
333                                 goto iter;
334                         if (strstr(item, prefix) != item) {
335                                 printf("found bad name %s\n", item);
336                                 exit(-1);
337                         }
338                         printf("[%03d]: %s\n",
339                                 index++, item + strlen(prefix));
340 iter:
341                         pos += ent->d_reclen;
342                 }
343         }
344         if (rc < 0) {
345                 printf("getdents error %d\n", rc);
346                 exit(-1);
347         }
348         if (index != nfiles) {
349                 printf("get %d files != %d\n", index, nfiles);
350                 exit(-1);
351         }
352         t_close(fd);
353         printf("Cleanup...\n");
354         for (i = 0; i < nfiles; i++) {
355                 sprintf(name, "%s%s%05d", dir, prefix, i);
356                 t_unlink(name);
357         }
358         t_rmdir(dir);
359         LEAVE();
360 }
361
362 void t15()
363 {
364         char file[MAX_PATH_LENGTH] = "";
365         int fd;
366         ENTRY("open-stat-close");
367         snprintf(file, MAX_PATH_LENGTH, "%s/test_t15_file", lustre_path);
368
369         t_touch(file);
370         fd = t_open(file);
371         t_check_stat(file, NULL);
372         t_close(fd);
373         t_unlink(file);
374         LEAVE();
375 }
376
377 void t16()
378 {
379         char file[MAX_PATH_LENGTH] = "";
380         ENTRY("small-write-read");
381         snprintf(file, MAX_PATH_LENGTH, "%s/test_t16_file", lustre_path);
382
383         t_echo_create(file, "aaaaaaaaaaaaaaaaaaaaaa");
384         t_grep(file, "aaaaaaaaaaaaaaaaaaaaaa");
385         t_unlink(file);
386         LEAVE();
387 }
388
389 void t17()
390 {
391         char file[MAX_PATH_LENGTH] = "";
392         int fd;
393         ENTRY("open-unlink without close");
394         snprintf(file, MAX_PATH_LENGTH, "%s/test_t17_file", lustre_path);
395
396         fd = open(file, O_WRONLY | O_CREAT, 0666);
397         if (fd < 0) {
398                 printf("failed to create file: %s\n", strerror(errno));
399                 exit(-1);
400         }
401         t_unlink(file);
402         LEAVE();
403 }
404
405 void t18()
406 {
407         char file[MAX_PATH_LENGTH] = "";
408         char buf[128];
409         int fd, i;
410         struct stat statbuf[3];
411         ENTRY("write should change mtime/atime");
412         snprintf(file, MAX_PATH_LENGTH, "%s/test_t18_file", lustre_path);
413
414         for (i = 0; i < 3; i++) {
415                 fd = open(file, O_RDWR|O_CREAT|O_APPEND, (mode_t)0666);
416                 if (fd < 0) {
417                         printf("error open file: %s\n", strerror(errno));
418                         exit(-1);
419                 }
420                 if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
421                         printf("error write file\n");
422                         exit(-1);
423                 }
424                 close(fd);
425                 if(stat(file, &statbuf[i]) != 0) {
426                         printf("Error stat\n");
427                         exit(1);
428                 }
429                 printf("mtime %lu, ctime %lu\n",
430                         statbuf[i].st_atime, statbuf[i].st_mtime);
431                 sleep(2);
432         }
433
434         for (i = 1; i < 3; i++) {
435                 if ((statbuf[i].st_atime <= statbuf[i-1].st_atime) ||
436                     (statbuf[i].st_mtime <= statbuf[i-1].st_mtime)) {
437                         printf("time error\n");
438                         exit(-1);
439                 }
440         }
441         t_unlink(file);
442         LEAVE();
443 }
444
445 void t19()
446 {
447         char file[MAX_PATH_LENGTH] = "";
448         int fd;
449         struct stat statbuf;
450         ENTRY("open(O_TRUNC) should trancate file to 0-length");
451         snprintf(file, MAX_PATH_LENGTH, "%s/test_t19_file", lustre_path);
452
453         t_echo_create(file, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
454
455         fd = open(file, O_RDWR|O_CREAT|O_TRUNC, (mode_t)0666);
456         if (fd < 0) {
457                 printf("error open file: %s\n", strerror(errno));
458                 exit(-1);
459         }
460         close(fd);
461         if(stat(file, &statbuf) != 0) {
462                 printf("Error stat\n");
463                 exit(1);
464         }
465         if (statbuf.st_size != 0) {
466                 printf("size %ld is not zero\n", statbuf.st_size);
467                 exit(-1);
468         }
469         t_unlink(file);
470         LEAVE();
471 }
472
473 void t20()
474 {
475         char file[MAX_PATH_LENGTH] = "";
476         int fd;
477         struct iovec iov[2];
478         char buf[100];
479         ssize_t ret;
480         ENTRY("trap app's general bad pointer for file i/o");
481         snprintf(file, MAX_PATH_LENGTH, "%s/test_t20_file", lustre_path);
482
483         fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
484         if (fd < 0) {
485                 printf("error open file: %s\n", strerror(errno));
486                 exit(-1);
487         }
488
489         ret = write(fd, NULL, 20);
490         if (ret != -1 || errno != EFAULT) {
491                 printf("write 1: ret %ld, errno %d\n", ret, errno);
492                 exit(1);
493         }
494         ret = write(fd, (void *)-1, 20);
495         if (ret != -1 || errno != EFAULT) {
496                 printf("write 2: ret %ld, errno %d\n", ret, errno);
497                 exit(1);
498         }
499         iov[0].iov_base = NULL;
500         iov[0].iov_len = 10;
501         iov[1].iov_base = (void *)-1;
502         iov[1].iov_len = 10;
503         ret = writev(fd, iov, 2);
504         if (ret != -1 || errno != EFAULT) {
505                 printf("writev 1: ret %ld, errno %d\n", ret, errno);
506                 exit(1);
507         }
508         iov[0].iov_base = NULL;
509         iov[0].iov_len = 0;
510         iov[1].iov_base = buf;
511         iov[1].iov_len = sizeof(buf);
512         ret = writev(fd, iov, 2);
513         if (ret != sizeof(buf)) {
514                 printf("write 3 ret %ld, error %d\n", ret, errno);
515                 exit(1);
516         }
517         lseek(fd, 0, SEEK_SET);
518
519         ret = read(fd, NULL, 20);
520         if (ret != -1 || errno != EFAULT) {
521                 printf("read 1: ret %ld, errno %d\n", ret, errno);
522                 exit(1);
523         }
524         ret = read(fd, (void *)-1, 20);
525         if (ret != -1 || errno != EFAULT) {
526                 printf("read 2: ret %ld, errno %d\n", ret, errno);
527                 exit(1);
528         }
529         iov[0].iov_base = NULL;
530         iov[0].iov_len = 10;
531         iov[1].iov_base = (void *)-1;
532         iov[1].iov_len = 10;
533         ret = readv(fd, iov, 2);
534         if (ret != -1 || errno != EFAULT) {
535                 printf("readv 1: ret %ld, errno %d\n", ret, errno);
536                 exit(1);
537         }
538         iov[0].iov_base = NULL;
539         iov[0].iov_len = 0;
540         iov[1].iov_base = buf;
541         iov[1].iov_len = sizeof(buf);
542         ret = readv(fd, iov, 2);
543         if (ret != sizeof(buf)) {
544                 printf("read 3 ret %ld, error %d\n", ret, errno);
545                 exit(1);
546         }
547
548         close(fd);
549         t_unlink(file);
550         LEAVE();
551 }
552
553 void t21()
554 {
555         char file[MAX_PATH_LENGTH] = "";
556         int fd, ret;
557         ENTRY("basic fcntl support");
558         snprintf(file, MAX_PATH_LENGTH, "%s/test_t21_file", lustre_path);
559
560         fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
561         if (fd < 0) {
562                 printf("error open file: %s\n", strerror(errno));
563                 exit(-1);
564         }
565         if (fcntl(fd, F_SETFL, O_APPEND)) {
566                 printf("error set flag: %s\n", strerror(errno));
567                 exit(-1);
568         }
569         if ((ret = fcntl(fd, F_GETFL)) != O_APPEND) {
570                 printf("error get flag: ret %x\n", ret);
571                 exit(-1);
572         }
573
574         close(fd);
575         t_unlink(file);
576         LEAVE();
577 }
578
579 void t22()
580 {
581         char file[MAX_PATH_LENGTH] = "";
582         int fd;
583         char *str = "1234567890";
584         char buf[100];
585         ssize_t ret;
586         ENTRY("make sure O_APPEND take effect");
587         snprintf(file, MAX_PATH_LENGTH, "%s/test_t22_file", lustre_path);
588
589         fd = open(file, O_RDWR|O_CREAT|O_APPEND, (mode_t)0666);
590         if (fd < 0) {
591                 printf("error open file: %s\n", strerror(errno));
592                 exit(-1);
593         }
594
595         lseek(fd, 100, SEEK_SET);
596         ret = write(fd, str, strlen(str));
597         if (ret != strlen(str)) {
598                 printf("write 1: ret %ld, errno %d\n", ret, errno);
599                 exit(1);
600         }
601
602         lseek(fd, 0, SEEK_SET);
603         ret = read(fd, buf, sizeof(buf));
604         if (ret != strlen(str)) {
605                 printf("read 1 got %ld\n", ret);
606                 exit(1);
607         }
608
609         if (memcmp(buf, str, strlen(str))) {
610                 printf("read 1 data err\n");
611                 exit(1);
612         }
613
614         if (fcntl(fd, F_SETFL, 0)) {
615                 printf("fcntl err: %s\n", strerror(errno));
616                 exit(1);
617         }
618
619         lseek(fd, 100, SEEK_SET);
620         ret = write(fd, str, strlen(str));
621         if (ret != strlen(str)) {
622                 printf("write 2: ret %ld, errno %d\n", ret, errno);
623                 exit(1);
624         }
625
626         lseek(fd, 100, SEEK_SET);
627         ret = read(fd, buf, sizeof(buf));
628         if (ret != strlen(str)) {
629                 printf("read 2 got %ld\n", ret);
630                 exit(1);
631         }
632
633         if (memcmp(buf, str, strlen(str))) {
634                 printf("read 2 data err\n");
635                 exit(1);
636         }
637
638         close(fd);
639         t_unlink(file);
640         LEAVE();
641 }
642
643
644 #define PAGE_SIZE (4096)
645 #define _npages (2048)
646
647 static int _buffer[_npages][PAGE_SIZE/sizeof(int)];
648
649 /* pos:   i/o start from
650  * xfer:  npages per transfer
651  */
652 static void pages_io(int xfer, loff_t pos)
653 {
654         char path[MAX_PATH_LENGTH] = "";
655
656         int check_sum[_npages] = {0,};
657         int fd, rc, i, j, data_error = 0;
658         struct timeval tw1, tw2, tr1, tr2;
659         double tw, tr;
660
661         snprintf(path, MAX_PATH_LENGTH, "%s/test_t50", lustre_path);
662         memset(_buffer, 0, sizeof(_buffer));
663
664         /* create sample data */
665         for (i = 0; i < _npages; i++) {
666                 for (j = 0; j < PAGE_SIZE/sizeof(int); j++) {
667                         _buffer[i][j] = rand();
668                 }
669         }
670
671         /* compute checksum */
672         for (i = 0; i < _npages; i++) {
673                 for (j = 0; j < PAGE_SIZE/sizeof(int); j++) {
674                         check_sum[i] += _buffer[i][j];
675                 }
676         }
677
678         t_touch(path);
679
680         fd = t_open(path);
681
682         /* write */
683         lseek(fd, pos, SEEK_SET);
684         gettimeofday(&tw1, NULL);
685         for (i = 0; i < _npages; i += xfer) {
686                 rc = write(fd, _buffer[i], PAGE_SIZE * xfer);
687                 if (rc != PAGE_SIZE * xfer) {
688                         printf("write error %d (i = %d)\n", rc, i);
689                         exit(1);
690                 }
691         }
692         gettimeofday(&tw2, NULL);
693
694         memset(_buffer, 0, sizeof(_buffer));
695
696         /* read */
697         lseek(fd, pos, SEEK_SET);
698         gettimeofday(&tr1, NULL);
699         for (i = 0; i < _npages; i += xfer) {
700                 rc = read(fd, _buffer[i], PAGE_SIZE * xfer);
701                 if (rc != PAGE_SIZE * xfer) {
702                         printf("read error %d (i = %d)\n", rc, i);
703                         exit(1);
704                 }
705         }
706         gettimeofday(&tr2, NULL);
707
708         /* compute checksum */
709         for (i = 0; i < _npages; i++) {
710                 int sum = 0;
711                 for (j = 0; j < PAGE_SIZE/sizeof(int); j++) {
712                         sum += _buffer[i][j];
713                 }
714                 if (sum != check_sum[i]) {
715                         data_error = 1;
716                         printf("chunk %d checksum error: expected 0x%x, get 0x%x\n",
717                                 i, check_sum[i], sum);
718                 }
719         }
720
721         t_close(fd);
722         t_unlink(path);
723         tw = (tw2.tv_sec - tw1.tv_sec) * 1000000 + (tw2.tv_usec - tw1.tv_usec);
724         tr = (tr2.tv_sec - tr1.tv_sec) * 1000000 + (tr2.tv_usec - tr1.tv_usec);
725         printf(" (R:%.3fM/s, W:%.3fM/s)\n",
726                 (_npages * PAGE_SIZE) / (tw / 1000000.0) / (1024 * 1024),
727                 (_npages * PAGE_SIZE) / (tr / 1000000.0) / (1024 * 1024));
728
729         if (data_error)
730                 exit(1);
731 }
732
733 void t50()
734 {
735         loff_t off_array[] = {1, 17, 255, 258, 4095, 4097, 8191,
736                               1024*1024*1024*1024ULL};
737         int np = 1, i;
738         loff_t offset = 0;
739
740         ENTRY("4k aligned i/o sanity");
741         while (np <= _npages) {
742                 printf("%3d per xfer(total %d)...\t", np, _npages);
743                 pages_io(np, offset);
744                 np += np;
745         }
746         LEAVE();
747
748         ENTRY("4k un-aligned i/o sanity");
749         for (i = 0; i < sizeof(off_array)/sizeof(loff_t); i++) {
750                 offset = off_array[i];
751                 printf("16 per xfer(total %d), offset %10lld...\t",
752                         _npages, offset);
753                 pages_io(16, offset);
754         }
755         LEAVE();
756 }
757
758 extern void __liblustre_setup_(void);
759 extern void __liblustre_cleanup_(void);
760
761 void usage(char *cmd)
762 {
763         printf("Usage: \t%s --target mdsnid:/mdsname/profile\n", cmd);
764         printf("       \t%s --dumpfile dumpfile\n", cmd);
765         exit(-1);
766 }
767
768 int main(int argc, char * const argv[])
769 {
770         int opt_index, c;
771         static struct option long_opts[] = {
772                 {"target", 1, 0, 0},
773                 {"dumpfile", 1, 0, 0},
774                 {0, 0, 0, 0}
775         };
776
777         if (argc <= 1)
778                 usage(argv[0]);
779
780         while ((c = getopt_long(argc, argv, "", long_opts, &opt_index)) != -1) {
781                 switch (c) {
782                 case 0: {
783                         if (!optarg[0])
784                                 usage(argv[0]);
785
786                         if (!strcmp(long_opts[opt_index].name, "target")) {
787                                 setenv(ENV_LUSTRE_MNTTGT, optarg, 1);
788                         } else if (!strcmp(long_opts[opt_index].name, "dumpfile")) {
789                                 setenv(ENV_LUSTRE_DUMPFILE, optarg, 1);
790                         } else
791                                 usage(argv[0]);
792                         break;
793                 }
794                 default:
795                         usage(argv[0]);
796                 }
797         }
798
799         if (optind != argc)
800                 usage(argv[0]);
801
802         __liblustre_setup_();
803
804         t1();
805         t2();
806         t3();
807         t4();
808         t6();
809         t7();
810         t8();
811         t9();
812         t10();
813         t11();
814         t12();
815         t13();
816         t14();
817         t15();
818         t16();
819         t17();
820         t18();
821         t19();
822         t20();
823         t21();
824         t22();
825         t50();
826
827         printf("liblustre is about shutdown\n");
828         __liblustre_cleanup_();
829
830         printf("complete successfully\n");
831         return 0;
832 }