1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see [sun.com URL with a
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
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
42 #include <sys/types.h>
45 #include <netinet/in.h>
46 #include <sys/socket.h>
51 char *dir = NULL, *dir2 = NULL;
53 char mmap_sanity[256];
56 static void usage(void)
58 printf("Usage: mmap_sanity -d dir [-m dir2]\n");
59 printf(" dir lustre mount point\n");
60 printf(" dir2 another mount point\n");
64 static int remote_tst(int tc, char *mnt);
65 static int mmap_run(int tc)
77 rc = remote_tst(tc, dir2);
80 fprintf(stderr, "invalid argument!\n");
85 static int mmap_initialize(char *myself)
87 char buf[1024], *file;
88 int fdr, fdw, count, rc = 0;
90 page_size = sysconf(_SC_PAGESIZE);
91 if (page_size == -1) {
92 perror("sysconf(_SC_PAGESIZE)");
96 /* copy myself to lustre for another client */
97 fdr = open(myself, O_RDONLY);
102 file = strrchr(myself, '/');
104 fprintf(stderr, "can't get test filename\n");
109 sprintf(mmap_sanity, "%s/%s", dir, file);
111 fdw = open(mmap_sanity, O_CREAT|O_WRONLY, 0777);
117 while ((count = read(fdr, buf, sizeof(buf))) != 0) {
125 writes = write(fdw, buf, count);
126 if (writes != count) {
137 static void mmap_finalize()
142 /* basic mmap operation on single node */
143 static int mmap_tst1(char *mnt)
145 char *ptr, mmap_file[256];
146 int region, fd, rc = 0;
148 region = page_size * 10;
149 sprintf(mmap_file, "%s/%s", mnt, "mmap_file1");
151 if (unlink(mmap_file) && errno != ENOENT) {
156 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
161 ftruncate(fd, region);
163 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
164 if (ptr == MAP_FAILED) {
169 memset(ptr, 'a', region);
178 /* MAP_PRIVATE create a copy-on-write mmap */
179 static int mmap_tst2(char *mnt)
181 char *ptr, mmap_file[256], buf[256];
184 sprintf(mmap_file, "%s/%s", mnt, "mmap_file2");
186 if (unlink(mmap_file) && errno != ENOENT) {
191 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
196 ftruncate(fd, page_size);
198 ptr = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
199 if (ptr == MAP_FAILED) {
204 memcpy(ptr, "blah", strlen("blah"));
206 munmap(ptr, page_size);
212 fd = open(mmap_file, O_RDONLY);
217 rc = read(fd, buf, sizeof(buf));
225 if (strncmp("blah", buf, strlen("blah")) == 0) {
226 fprintf(stderr, "mmap write back with MAP_PRIVATE!\n");
234 /* concurrent mmap operations on two nodes */
235 static int mmap_tst3(char *mnt)
237 char *ptr, mmap_file[256];
238 int region, fd, rc = 0;
240 region = page_size * 100;
241 sprintf(mmap_file, "%s/%s", mnt, "mmap_file3");
243 if (unlink(mmap_file) && errno != ENOENT) {
248 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
253 ftruncate(fd, region);
255 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
256 if (ptr == MAP_FAILED) {
266 memset(ptr, 'a', region);
267 sleep(2); /* wait for remote test finish */
276 static int remote_tst3(char *mnt)
278 char *ptr, mmap_file[256];
279 int region, fd, rc = 0;
281 region = page_size * 100;
282 sprintf(mmap_file, "%s/%s", mnt, "mmap_file3");
284 fd = open(mmap_file, O_RDWR, 0600);
290 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
291 if (ptr == MAP_FAILED) {
296 memset(ptr, 'b', region);
297 memset(ptr, 'c', region);
305 /* client1 write to file_4a from mmap()ed file_4b;
306 * client2 write to file_4b from mmap()ed file_4a. */
307 static int mmap_tst4(char *mnt)
309 char *ptr, filea[256], fileb[256];
310 int region, fdr, fdw, rc = 0;
312 region = page_size * 100;
313 sprintf(filea, "%s/%s", mnt, "mmap_file_4a");
314 sprintf(fileb, "%s/%s", mnt, "mmap_file_4b");
316 if (unlink(filea) && errno != ENOENT) {
320 if (unlink(fileb) && errno != ENOENT) {
326 fdr = open(fileb, O_CREAT|O_RDWR, 0600);
331 ftruncate(fdr, region);
332 fdw = open(filea, O_CREAT|O_RDWR, 0600);
338 ftruncate(fdw, region);
340 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fdr, 0);
341 if (ptr == MAP_FAILED) {
351 memset(ptr, '1', region);
353 rc = write(fdw, ptr, region);
360 sleep(2); /* wait for remote test finish */
373 static int remote_tst4(char *mnt)
375 char *ptr, filea[256], fileb[256];
376 int region, fdr, fdw, rc = 0;
378 region = page_size * 100;
379 sprintf(filea, "%s/%s", mnt, "mmap_file_4a");
380 sprintf(fileb, "%s/%s", mnt, "mmap_file_4b");
383 fdr = open(filea, O_RDWR, 0600);
388 fdw = open(fileb, O_RDWR, 0600);
395 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fdr, 0);
396 if (ptr == MAP_FAILED) {
402 memset(ptr, '2', region);
404 rc = write(fdw, ptr, region);
420 static int cancel_lru_locks(char *prefix)
422 char cmd[256], line[1024];
425 int len = 1024, rc = 0;
432 rc = waitpid(child, &status, WNOHANG);
439 sprintf(cmd, "ls /proc/fs/lustre/ldlm/namespaces/*-%s-*/lru_size", prefix);
441 sprintf(cmd, "ls /proc/fs/lustre/ldlm/namespaces/*/lru_size");
443 file = popen(cmd, "r");
449 while (fgets(line, len, file)) {
454 /* trim newline character */
455 *(line + strlen(line) - 1) = '\0';
456 f = fopen(line, "w");
462 rc = fwrite("clear", strlen("clear") + 1, 1, f);
476 /* don't dead lock while read/write file to/from the buffer which
477 * mmaped to just this file */
478 static int mmap_tst5(char *mnt)
480 char *ptr, mmap_file[256];
481 int region, fd, off, rc = 0;
483 region = page_size * 40;
484 off = page_size * 10;
485 sprintf(mmap_file, "%s/%s", mnt, "mmap_file5");
487 if (unlink(mmap_file) && errno != ENOENT) {
492 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
497 ftruncate(fd, region);
499 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
500 if (ptr == MAP_FAILED) {
505 memset(ptr, 'a', region);
507 /* cancel unused locks */
508 rc = cancel_lru_locks("osc");
512 /* read/write region of file and buffer should be overlap */
513 rc = read(fd, ptr + off, off * 2);
519 rc = write(fd, ptr + off, off * 2);
533 /* mmap write to a file form client1 then mmap read from client2 */
534 static int mmap_tst6(char *mnt)
536 char mmap_file[256], mmap_file2[256];
537 char *ptr = NULL, *ptr2 = NULL;
538 int fd = 0, fd2 = 0, rc = 0;
540 sprintf(mmap_file, "%s/%s", mnt, "mmap_file6");
541 sprintf(mmap_file2, "%s/%s", dir2, "mmap_file6");
542 if (unlink(mmap_file) && errno != ENOENT) {
547 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
552 ftruncate(fd, page_size);
554 fd2 = open(mmap_file2, O_RDWR, 0600);
560 ptr = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
561 if (ptr == MAP_FAILED) {
567 ptr2 = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
568 if (ptr2 == MAP_FAILED) {
574 rc = cancel_lru_locks("osc");
578 memcpy(ptr, "blah", strlen("blah"));
579 if (strncmp(ptr, ptr2, strlen("blah"))) {
580 fprintf(stderr, "client2 mmap mismatch!\n");
584 memcpy(ptr2, "foo", strlen("foo"));
585 if (strncmp(ptr, ptr2, strlen("foo"))) {
586 fprintf(stderr, "client1 mmap mismatch!\n");
591 munmap(ptr2, page_size);
593 munmap(ptr, page_size);
602 static int remote_tst(int tc, char *mnt)
607 rc = remote_tst3(mnt);
610 rc = remote_tst4(mnt);
613 fprintf(stderr, "wrong test case number %d\n", tc);
621 int tc; /* test case number */
622 char *desc; /* test description */
623 int (* test_fn)(char *mnt); /* test function */
624 int node_cnt; /* node count */
627 struct test_case tests[] = {
628 { 1, "mmap test1: basic mmap operation", mmap_tst1, 1 },
629 { 2, "mmap test2: MAP_PRIVATE not write back", mmap_tst2, 1 },
630 { 3, "mmap test3: concurrent mmap ops on two nodes", mmap_tst3, 2 },
631 { 4, "mmap test4: c1 write to f1 from mmapped f2, "
632 "c2 write to f1 from mmapped f1", mmap_tst4, 2 },
633 { 5, "mmap test5: read/write file to/from the buffer "
634 "which mmapped to just this file", mmap_tst5, 1 },
635 { 6, "mmap test6: check mmap write/read content on two nodes",
640 int main(int argc, char **argv)
643 struct test_case *test;
647 c = getopt(argc, argv, "d:m:");
668 if (mmap_initialize(argv[0]) != 0) {
669 fprintf(stderr, "mmap_initialize failed!\n");
673 for (test = tests; test->tc; test++) {
676 if (test->node_cnt == 1 || dir2 != NULL) {
677 rc = test->test_fn(dir);
678 rs = rc ? "fail" : "pass";
680 fprintf(stderr, "%s (%s)\n", test->desc, rs);