1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
12 #include <netinet/in.h>
13 #include <sys/socket.h>
18 char *dir = NULL, *dir2 = NULL;
20 char mmap_sanity[256];
23 static void usage(void)
25 printf("Usage: mmap_sanity -d dir [-m dir2]\n");
26 printf(" dir lustre mount point\n");
27 printf(" dir2 another mount point\n");
31 static int remote_tst(int tc, char *mnt);
32 static int mmap_run(int tc)
44 rc = remote_tst(tc, dir2);
47 fprintf(stderr, "invalid argument!\n");
52 static int mmap_initialize(char *myself)
54 char buf[1024], *file;
55 int fdr, fdw, count, rc = 0;
57 page_size = sysconf(_SC_PAGESIZE);
58 if (page_size == -1) {
59 perror("sysconf(_SC_PAGESIZE)");
63 /* copy myself to lustre for another client */
64 fdr = open(myself, O_RDONLY);
69 file = strrchr(myself, '/');
71 fprintf(stderr, "can't get test filename\n");
76 sprintf(mmap_sanity, "%s/%s", dir, file);
78 fdw = open(mmap_sanity, O_CREAT|O_WRONLY, 0777);
84 while ((count = read(fdr, buf, sizeof(buf))) != 0) {
92 writes = write(fdw, buf, count);
93 if (writes != count) {
104 static void mmap_finalize()
109 /* basic mmap operation on single node */
110 static int mmap_tst1(char *mnt)
112 char *ptr, mmap_file[256];
113 int region, fd, rc = 0;
115 region = page_size * 10;
116 sprintf(mmap_file, "%s/%s", mnt, "mmap_file1");
118 if (unlink(mmap_file) && errno != ENOENT) {
123 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
128 ftruncate(fd, region);
130 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
131 if (ptr == MAP_FAILED) {
136 memset(ptr, 'a', region);
145 /* MAP_PRIVATE create a copy-on-write mmap */
146 static int mmap_tst2(char *mnt)
148 char *ptr, mmap_file[256], buf[256];
151 sprintf(mmap_file, "%s/%s", mnt, "mmap_file2");
153 if (unlink(mmap_file) && errno != ENOENT) {
158 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
163 ftruncate(fd, page_size);
165 ptr = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
166 if (ptr == MAP_FAILED) {
171 memcpy(ptr, "blah", strlen("blah"));
173 munmap(ptr, page_size);
179 fd = open(mmap_file, O_RDONLY);
184 rc = read(fd, buf, sizeof(buf));
192 if (strncmp("blah", buf, strlen("blah")) == 0) {
193 fprintf(stderr, "mmap write back with MAP_PRIVATE!\n");
201 /* concurrent mmap operations on two nodes */
202 static int mmap_tst3(char *mnt)
204 char *ptr, mmap_file[256];
205 int region, fd, rc = 0;
207 region = page_size * 100;
208 sprintf(mmap_file, "%s/%s", mnt, "mmap_file3");
210 if (unlink(mmap_file) && errno != ENOENT) {
215 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
220 ftruncate(fd, region);
222 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
223 if (ptr == MAP_FAILED) {
233 memset(ptr, 'a', region);
234 sleep(2); /* wait for remote test finish */
243 static int remote_tst3(char *mnt)
245 char *ptr, mmap_file[256];
246 int region, fd, rc = 0;
248 region = page_size * 100;
249 sprintf(mmap_file, "%s/%s", mnt, "mmap_file3");
251 fd = open(mmap_file, O_RDWR, 0600);
257 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
258 if (ptr == MAP_FAILED) {
263 memset(ptr, 'b', region);
264 memset(ptr, 'c', region);
272 /* client1 write to file_4a from mmap()ed file_4b;
273 * client2 write to file_4b from mmap()ed file_4a. */
274 static int mmap_tst4(char *mnt)
276 char *ptr, filea[256], fileb[256];
277 int region, fdr, fdw, rc = 0;
279 region = page_size * 100;
280 sprintf(filea, "%s/%s", mnt, "mmap_file_4a");
281 sprintf(fileb, "%s/%s", mnt, "mmap_file_4b");
283 if (unlink(filea) && errno != ENOENT) {
287 if (unlink(fileb) && errno != ENOENT) {
293 fdr = open(fileb, O_CREAT|O_RDWR, 0600);
298 ftruncate(fdr, region);
299 fdw = open(filea, O_CREAT|O_RDWR, 0600);
305 ftruncate(fdw, region);
307 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fdr, 0);
308 if (ptr == MAP_FAILED) {
318 memset(ptr, '1', region);
320 rc = write(fdw, ptr, region);
327 sleep(2); /* wait for remote test finish */
340 static int remote_tst4(char *mnt)
342 char *ptr, filea[256], fileb[256];
343 int region, fdr, fdw, rc = 0;
345 region = page_size * 100;
346 sprintf(filea, "%s/%s", mnt, "mmap_file_4a");
347 sprintf(fileb, "%s/%s", mnt, "mmap_file_4b");
350 fdr = open(filea, O_RDWR, 0600);
355 fdw = open(fileb, O_RDWR, 0600);
362 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fdr, 0);
363 if (ptr == MAP_FAILED) {
369 memset(ptr, '2', region);
371 rc = write(fdw, ptr, region);
387 static int cancel_lru_locks(char *prefix)
389 char cmd[256], line[1024];
392 int len = 1024, rc = 0;
399 rc = waitpid(child, &status, WNOHANG);
406 sprintf(cmd, "ls /proc/fs/lustre/ldlm/namespaces/*-%s-*/lru_size", prefix);
408 sprintf(cmd, "ls /proc/fs/lustre/ldlm/namespaces/*/lru_size");
410 file = popen(cmd, "r");
416 while (fgets(line, len, file)) {
421 /* trim newline character */
422 *(line + strlen(line) - 1) = '\0';
423 f = fopen(line, "w");
429 rc = fwrite("clear", strlen("clear") + 1, 1, f);
443 /* don't dead lock while read/write file to/from the buffer which
444 * mmaped to just this file */
445 static int mmap_tst5(char *mnt)
447 char *ptr, mmap_file[256];
448 int region, fd, off, rc = 0;
450 region = page_size * 40;
451 off = page_size * 10;
452 sprintf(mmap_file, "%s/%s", mnt, "mmap_file5");
454 if (unlink(mmap_file) && errno != ENOENT) {
459 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
464 ftruncate(fd, region);
466 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
467 if (ptr == MAP_FAILED) {
472 memset(ptr, 'a', region);
474 /* cancel unused locks */
475 cancel_lru_locks("osc");
479 /* read/write region of file and buffer should be overlap */
480 rc = read(fd, ptr + off, off * 2);
486 rc = write(fd, ptr + off, off * 2);
500 /* mmap write to a file form client1 then mmap read from client2 */
501 static int mmap_tst6(char *mnt)
503 char mmap_file[256], mmap_file2[256];
504 char *ptr = NULL, *ptr2 = NULL;
505 int fd = 0, fd2 = 0, rc = 0;
507 sprintf(mmap_file, "%s/%s", mnt, "mmap_file6");
508 sprintf(mmap_file2, "%s/%s", dir2, "mmap_file6");
509 if (unlink(mmap_file) && errno != ENOENT) {
514 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
519 ftruncate(fd, page_size);
521 fd2 = open(mmap_file2, O_RDWR, 0600);
527 ptr = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
528 if (ptr == MAP_FAILED) {
534 ptr2 = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
535 if (ptr2 == MAP_FAILED) {
541 cancel_lru_locks("osc");
545 memcpy(ptr, "blah", strlen("blah"));
546 if (strncmp(ptr, ptr2, strlen("blah"))) {
547 fprintf(stderr, "client2 mmap mismatch!\n");
551 memcpy(ptr2, "foo", strlen("foo"));
552 if (strncmp(ptr, ptr2, strlen("foo"))) {
553 fprintf(stderr, "client1 mmap mismatch!\n");
558 munmap(ptr2, page_size);
560 munmap(ptr, page_size);
569 static int remote_tst(int tc, char *mnt)
574 rc = remote_tst3(mnt);
577 rc = remote_tst4(mnt);
580 fprintf(stderr, "wrong test case number %d\n", tc);
588 int tc; /* test case number */
589 char *desc; /* test description */
590 int (* test_fn)(char *mnt); /* test function */
591 int node_cnt; /* node count */
594 struct test_case tests[] = {
595 { 1, "mmap test1: basic mmap operation", mmap_tst1, 1 },
596 { 2, "mmap test2: MAP_PRIVATE not write back", mmap_tst2, 1 },
597 { 3, "mmap test3: concurrent mmap ops on two nodes", mmap_tst3, 2 },
598 { 4, "mmap test4: c1 write to f1 from mmapped f2, "
599 "c2 write to f1 from mmapped f1", mmap_tst4, 2 },
600 { 5, "mmap test5: read/write file to/from the buffer "
601 "which mmapped to just this file", mmap_tst5, 1 },
602 { 6, "mmap test6: check mmap write/read content on two nodes",
607 int main(int argc, char **argv)
610 struct test_case *test;
614 c = getopt(argc, argv, "d:m:");
635 if (mmap_initialize(argv[0]) != 0) {
636 fprintf(stderr, "mmap_initialize failed!\n");
640 for (test = tests; test->tc; test++) {
643 if (test->node_cnt == 1 || dir2 != NULL) {
644 rc = test->test_fn(dir);
645 rs = rc ? "fail" : "pass";
647 fprintf(stderr, "%s (%s)\n", test->desc, rs);