Whamcloud - gitweb
- landing of b_hd_cleanup_merge to HEAD.
[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
39 #include "test_common.h"
40
41 #define ENTRY(str)                                                      \
42         do {                                                            \
43                 char buf[100];                                          \
44                 int len;                                                \
45                 sprintf(buf, "===== START: %s ", (str));                \
46                 len = strlen(buf);                                      \
47                 if (len < 79) {                                         \
48                         memset(buf+len, '=', 100-len);                  \
49                         buf[79] = '\n';                                 \
50                         buf[80] = 0;                                    \
51                 }                                                       \
52                 printf("%s", buf);                                      \
53         } while (0)
54
55 #define LEAVE()                                                         \
56         do {                                                            \
57                 printf("----- END TEST successfully ---");              \
58                 printf("-----------------------------");                \
59                 printf("-------------------\n");                        \
60         } while (0)
61
62 #define MAX_PATH_LENGTH 4096
63
64 void t1()
65 {
66         char *path="/mnt/lustre/test_t1";
67         ENTRY("create/delete");
68
69         t_touch(path);
70         t_unlink(path);
71         LEAVE();
72 }
73
74 void t2()
75 {
76         char *path="/mnt/lustre/test_t2";
77         ENTRY("mkdir/rmdir");
78
79         t_mkdir(path);
80         t_rmdir(path);
81         LEAVE();
82 }
83
84 void t3()
85 {
86         char *path="/mnt/lustre/test_t3";
87         ENTRY("regular stat");
88
89         t_touch(path);
90         t_check_stat(path, NULL);
91         t_unlink(path);
92         LEAVE();
93 }
94
95 void t4()
96 {
97         char *path="/mnt/lustre/test_t4";
98         ENTRY("dir stat");
99
100         t_mkdir(path);
101         t_check_stat(path, NULL);
102         t_rmdir(path);
103         LEAVE();
104 }
105
106 void t6()
107 {
108         char *path="/mnt/lustre/test_t6";
109         char *path2="/mnt/lustre/test_t6_link";
110         ENTRY("symlink");
111
112         t_touch(path);
113         t_symlink(path, path2);
114         t_check_stat(path2, NULL);
115         t_unlink(path2);
116         t_unlink(path);
117         LEAVE();
118 }
119
120 void t7()
121 {
122         char *path="/mnt/lustre/test_t7";
123         int rc;
124         ENTRY("mknod");
125
126         if (geteuid() != 0) {
127                 rc = mknod(path, S_IFCHR | 0644, (5<<8 | 4));
128                 if (rc != -1 || errno != EPERM) {
129                         printf("mknod shouldn't success: rc %d, errno %d\n",
130                                 rc, errno);
131                 }
132         } else {
133                 t_mknod(path, S_IFCHR | 0644, 5, 4);
134                 t_check_stat(path, NULL);
135                 t_unlink(path);
136         }
137         LEAVE();
138 }
139
140 void t8()
141 {
142         char *path="/mnt/lustre/test_t8";
143         ENTRY("chmod");
144
145         t_touch(path);
146         t_chmod_raw(path, 0700);
147         t_check_stat(path, NULL);
148         t_unlink(path);
149         LEAVE();
150 }
151
152 void t9()
153 {
154         char *path="/mnt/lustre/test_t9";
155         char *path2="/mnt/lustre/test_t9_link";
156         ENTRY("hard link");
157
158         t_touch(path);
159         t_link(path, path2);
160         t_check_stat(path, NULL);
161         t_check_stat(path2, NULL);
162         t_unlink(path);
163         t_unlink(path2);
164         LEAVE();
165 }
166
167 void t10()
168 {
169         char *dir1="/mnt/lustre/test_t10_dir1";
170         char *dir2="/mnt/lustre/test_t10_dir2";
171         char *path1="/mnt/lustre/test_t10_reg1";
172         char *path2="/mnt/lustre/test_t10_reg2";
173         char *rename1="/mnt/lustre/test_t10_dir1/rename1";
174         char *rename2="/mnt/lustre/test_t10_dir2/rename2";
175         char *rename3="/mnt/lustre/test_t10_dir2/rename3";
176         ENTRY("rename");
177
178         t_mkdir(dir1);
179         t_mkdir(dir2);
180         t_touch(path1);
181         t_touch(path2);
182         t_rename(path1, rename1);
183         t_rename(path2, rename2);
184         t_rename(rename1, rename2);
185         t_rename(dir1, rename3);
186         t_unlink(rename2);
187         t_rmdir(rename3);
188         t_rmdir(dir2);
189         LEAVE();
190 }
191
192 void t11()
193 {
194         char *base="/mnt/lustre";
195         char path[MAX_PATH_LENGTH], path2[MAX_PATH_LENGTH];
196         int i, j, level = 5, nreg = 5;
197         ENTRY("deep tree");
198
199         safe_strncpy(path, base, MAX_PATH_LENGTH);
200
201         for (i = 0; i < level; i++) {
202                 for (j = 0; j < nreg; j++) {
203                         sprintf(path2, "%s/file%d", path, j);
204                         t_touch(path2);
205                 }
206
207                 strcat(path, "/dir");
208                 t_mkdir(path);
209         }
210
211         for (i = level; i > 0; i--) {
212                 safe_strncpy(path, base, MAX_PATH_LENGTH);
213                 for (j = 1; j < i; j++)
214                         strcat(path, "/dir");
215                 
216                 for (j = 0; j < nreg; j++) {
217                         sprintf(path2, "%s/file%d", path, j);
218                         t_unlink(path2);
219                 }
220
221                 strcat(path, "/dir");
222                 t_rmdir(path);
223         }
224
225         LEAVE();
226 }
227
228 void t12()
229 {
230         char *dir="/mnt/lustre/test_t12_dir";
231         char buf[1024*128];
232         int fd;
233         ENTRY("empty directory readdir");
234
235         t_mkdir(dir);
236         fd = t_opendir(dir);
237         t_ls(fd, buf, sizeof(buf));
238         t_close(fd);
239         t_rmdir(dir);
240         LEAVE();
241 }
242
243 void t13()
244 {
245         char *dir="/mnt/lustre/test_t13_dir/";
246         char name[1024];
247         char buf[1024];
248         const int nfiles = 20;
249         char *prefix = "test13_filename_prefix_";
250         int fd, i;
251         ENTRY("multiple entries directory readdir");
252
253         t_mkdir(dir);
254         printf("Creating %d files...\n", nfiles);
255         for (i = 0; i < nfiles; i++) {
256                 sprintf(name, "%s%s%05d", dir, prefix, i);
257                 t_touch(name);
258         }
259         fd = t_opendir(dir);
260         t_ls(fd, buf, sizeof(buf));
261         t_close(fd);
262         printf("Cleanup...\n");
263         for (i = 0; i < nfiles; i++) {
264                 sprintf(name, "%s%s%05d", dir, prefix, i);
265                 t_unlink(name);
266         }
267         t_rmdir(dir);
268         LEAVE();
269 }
270
271 void t14()
272 {
273         char *dir="/mnt/lustre/test_t14_dir/";
274         char name[1024];
275         char buf[1024];
276         const int nfiles = 256;
277         char *prefix = "test14_filename_long_prefix_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA___";
278         struct dirent64 *ent;
279         int fd, i, rc, pos, index;
280         loff_t base = 0;
281         ENTRY(">1 block(4k) directory readdir");
282
283         t_mkdir(dir);
284         printf("Creating %d files...\n", nfiles);
285         for (i = 0; i < nfiles; i++) {
286                 sprintf(name, "%s%s%05d", dir, prefix, i);
287                 t_touch(name);
288         }
289         fd = t_opendir(dir);
290         printf("Listing...\n");
291         index = 0;
292         while ((rc = getdirentries64(fd, buf, 1024, &base)) > 0) {
293                 pos = 0;
294                 while (pos < rc) {
295                         char *item;
296
297                         ent = (struct dirent64 *) ((char*) buf + pos);
298                         item = (char *) ent->d_name;
299                         if (!strcmp(item, ".") || !strcmp(item, ".."))
300                                 goto iter;
301                         if (strstr(item, prefix) != item) {
302                                 printf("found bad name %s\n", item);
303                                 exit(-1);
304                         }
305                         printf("[%03d]: %s\n",
306                                 index++, item + strlen(prefix));
307 iter:
308                         pos += ent->d_reclen;
309                 }
310         }
311         if (rc < 0) {
312                 printf("getdents error %d\n", rc);
313                 exit(-1);
314         }
315         if (index != nfiles) {
316                 printf("get %d files != %d\n", index, nfiles);
317                 exit(-1);
318         }
319         t_close(fd);
320         printf("Cleanup...\n");
321         for (i = 0; i < nfiles; i++) {
322                 sprintf(name, "%s%s%05d", dir, prefix, i);
323                 t_unlink(name);
324         }
325         t_rmdir(dir);
326         LEAVE();
327 }
328
329 void t15()
330 {
331         char *file = "/mnt/lustre/test_t15_file";
332         int fd;
333         ENTRY("open-stat-close");
334
335         t_touch(file);
336         fd = t_open(file);
337         t_check_stat(file, NULL);
338         t_close(fd);
339         t_unlink(file);
340         LEAVE();
341 }
342
343 void t16()
344 {
345         char *file = "/mnt/lustre/test_t16_file";
346         int fd;
347         ENTRY("small-write-read");
348
349         t_echo_create(file, "aaaaaaaaaaaaaaaaaaaaaa");
350         t_grep(file, "aaaaaaaaaaaaaaaaaaaaaa");
351         t_unlink(file);
352         LEAVE();
353 }
354
355 void t17()
356 {
357         char *file = "/mnt/lustre/test_t17_file";
358         int fd;
359         ENTRY("open-unlink without close");
360
361         fd = open(file, O_WRONLY | O_CREAT, 0666);
362         if (fd < 0) {
363                 printf("failed to create file: %s\n", strerror(errno));
364                 exit(-1);
365         }
366         t_unlink(file);
367         LEAVE();
368 }
369
370 void t18()
371 {
372         char *file = "/mnt/lustre/test_t18_file";
373         char buf[128];
374         int fd, i;
375         struct stat statbuf[3];
376         ENTRY("write should change mtime/atime");
377
378         for (i = 0; i < 3; i++) {
379                 fd = open(file, O_RDWR|O_CREAT|O_APPEND, (mode_t)0666);
380                 if (fd < 0) {
381                         printf("error open file: %s\n", strerror(errno));
382                         exit(-1);
383                 }
384                 if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
385                         printf("error write file\n");
386                         exit(-1);
387                 }
388                 close(fd);
389                 if(stat(file, &statbuf[i]) != 0) {
390                         printf("Error stat\n");
391                         exit(1);
392                 }
393                 printf("mtime %ld, ctime %d\n",
394                         statbuf[i].st_atime, statbuf[i].st_mtime);
395                 sleep(2);
396         }
397
398         for (i = 1; i < 3; i++) {
399                 if ((statbuf[i].st_atime <= statbuf[i-1].st_atime) ||
400                     (statbuf[i].st_mtime <= statbuf[i-1].st_mtime)) {
401                         printf("time error\n");
402                         exit(-1);
403                 }
404         }
405         t_unlink(file);
406 }
407
408 #define PAGE_SIZE (4096)
409 #define _npages (2048)
410
411 static int _buffer[_npages][PAGE_SIZE/sizeof(int)];
412
413 /* pos:   i/o start from
414  * xfer:  npages per transfer
415  */
416 static void pages_io(int xfer, loff_t pos)
417 {
418         char *path="/mnt/lustre/test_t50";
419         int check_sum[_npages] = {0,};
420         int fd, rc, i, j;
421         struct timeval tw1, tw2, tr1, tr2;
422         double tw, tr;
423
424         memset(_buffer, 0, sizeof(_buffer));
425
426         /* create sample data */
427         for (i = 0; i < _npages; i++) {
428                 for (j = 0; j < PAGE_SIZE/sizeof(int); j++) {
429                         _buffer[i][j] = rand();
430                 }
431         }
432
433         /* compute checksum */
434         for (i = 0; i < _npages; i++) {
435                 for (j = 0; j < PAGE_SIZE/sizeof(int); j++) {
436                         check_sum[i] += _buffer[i][j];
437                 }
438         }
439
440         t_touch(path);
441
442         fd = t_open(path);
443
444         /* write */
445         lseek(fd, pos, SEEK_SET);
446         gettimeofday(&tw1, NULL);
447         for (i = 0; i < _npages; i += xfer) {
448                 rc = write(fd, _buffer[i], PAGE_SIZE * xfer);
449                 if (rc != PAGE_SIZE * xfer) {
450                         printf("write error %d (i = %d)\n", rc, i);
451                         exit(1);
452                 }
453         }
454         gettimeofday(&tw2, NULL);
455
456         memset(_buffer, 0, sizeof(_buffer));
457
458         /* read */
459         lseek(fd, pos, SEEK_SET);
460         gettimeofday(&tr1, NULL);
461         for (i = 0; i < _npages; i += xfer) {
462                 rc = read(fd, _buffer[i], PAGE_SIZE * xfer);
463                 if (rc != PAGE_SIZE * xfer) {
464                         printf("read error %d (i = %d)\n", rc, i);
465                         exit(1);
466                 }
467         }
468         gettimeofday(&tr2, NULL);
469
470         /* compute checksum */
471         for (i = 0; i < _npages; i++) {
472                 int sum = 0;
473                 for (j = 0; j < PAGE_SIZE/sizeof(int); j++) {
474                         sum += _buffer[i][j];
475                 }
476                 if (sum != check_sum[i]) {
477                         printf("chunk %d checksum error: expected 0x%x, get 0x%x\n",
478                                 i, check_sum[i], sum);
479                 }
480         }
481
482         t_close(fd);
483         t_unlink(path);
484         tw = (tw2.tv_sec - tw1.tv_sec) * 1000000 + (tw2.tv_usec - tw1.tv_usec);
485         tr = (tr2.tv_sec - tr1.tv_sec) * 1000000 + (tr2.tv_usec - tr1.tv_usec);
486         printf(" (R:%.3fM/s, W:%.3fM/s)\n",
487                 (_npages * PAGE_SIZE) / (tw / 1000000.0) / (1024 * 1024),
488                 (_npages * PAGE_SIZE) / (tr / 1000000.0) / (1024 * 1024));
489 }
490
491 void t50()
492 {
493         char text[256];
494         loff_t off_array[] = {1, 17, 255, 258, 4095, 4097, 8191, 1024*1024*1024*1024ULL};
495         int np = 1, i;
496         loff_t offset = 0;
497
498         ENTRY("4k aligned i/o sanity");
499         while (np <= _npages) {
500                 printf("%3d per xfer(total %d)...\t", np, _npages);
501                 pages_io(np, offset);
502                 np += np;
503         }
504         LEAVE();
505
506         ENTRY("4k un-aligned i/o sanity");
507         for (i = 0; i < sizeof(off_array)/sizeof(loff_t); i++) {
508                 offset = off_array[i];
509                 printf("16 per xfer(total %d), offset %10lld...\t",
510                         _npages, offset);
511                 pages_io(16, offset);
512         }
513         LEAVE();
514 }
515
516 extern void __liblustre_setup_(void);
517 extern void __liblustre_cleanup_(void);
518
519 void usage(char *cmd)
520 {
521         printf("Usage: \t%s --target mdsnid:/mdsname/profile\n", cmd);
522         printf("       \t%s --dumpfile dumpfile\n", cmd);
523         exit(-1);
524 }
525
526 int main(int argc, char * const argv[])
527 {
528         int opt_index, c;
529         static struct option long_opts[] = {
530                 {"target", 1, 0, 0},
531                 {"dumpfile", 1, 0, 0},
532                 {0, 0, 0, 0}
533         };
534
535         if (argc <= 1)
536                 usage(argv[0]);
537
538         while ((c = getopt_long(argc, argv, "", long_opts, &opt_index)) != -1) {
539                 switch (c) {
540                 case 0: {
541                         if (!optarg[0])
542                                 usage(argv[0]);
543
544                         if (!strcmp(long_opts[opt_index].name, "target")) {
545                                 setenv(ENV_LUSTRE_MNTTGT, optarg, 1);
546                         } else if (!strcmp(long_opts[opt_index].name, "dumpfile")) {
547                                 setenv(ENV_LUSTRE_DUMPFILE, optarg, 1);
548                         } else
549                                 usage(argv[0]);
550                         break;
551                 }
552                 default:
553                         usage(argv[0]);
554                 }
555         }
556
557         if (optind != argc)
558                 usage(argv[0]);
559
560         __liblustre_setup_();
561
562         t1();
563         t2();
564         t3();
565         t4();
566         t6();
567         t7();
568         t8();
569         t9();
570         t10();
571         t11();
572         t12();
573         t13();
574         t14();
575         t15();
576         t16();
577         t17();
578         t18();
579         t50();
580
581         printf("liblustre is about shutdown\n");
582         __liblustre_cleanup_();
583
584         printf("complete successfully\n");
585         return 0;
586 }