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>
17 char *dir = NULL, *node = NULL, *dir2 = NULL;
19 char mmap_sanity[256];
22 static void usage(void)
24 printf("Usage: mmap_sanity -d dir [-n node | -m dir2]\n");
25 printf(" dir lustre mount point\n");
26 printf(" node another client\n");
27 printf(" dir2 another mount point\n");
31 #define MMAP_NOTIFY_PORT 7676
32 static int mmap_notify(char *target, char *str, int delay)
34 unsigned short port = MMAP_NOTIFY_PORT;
35 int socket_type = SOCK_DGRAM;
36 struct sockaddr_in server;
38 int len, sockfd, rc = 0;
43 sockfd = socket(AF_INET, socket_type, 0);
49 if ((hp = gethostbyname(target)) == NULL) {
55 memset(&server,0,sizeof(server));
56 memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
57 server.sin_family = AF_INET;
58 server.sin_port = htons(port);
64 rc = sendto(sockfd, str, strlen(str), 0,
65 (struct sockaddr *)&server, len);
77 static int mmap_wait(char *str, int timeout)
79 unsigned short port = MMAP_NOTIFY_PORT;
80 int socket_type = SOCK_DGRAM;
81 struct sockaddr_in local, from;
91 memset(host, 0, sizeof(host));
92 if (gethostname(host, sizeof(host))) {
93 perror("gethostname()");
97 if ((hp = gethostbyname(host)) == NULL) {
102 local.sin_family = AF_INET;
103 memcpy(&(local.sin_addr), hp->h_addr, hp->h_length);
104 local.sin_port = htons(port);
106 sockfd = socket(AF_INET, socket_type, 0);
112 rc = bind(sockfd, (struct sockaddr *)&local, sizeof(local));
120 FD_SET(sockfd, &rfds);
121 tv.tv_sec = timeout ? timeout : 5;
124 rc = select(sockfd + 1, &rfds, NULL, NULL, &tv);
125 if (rc) { /* got data */
127 int fromlen =sizeof(from);
129 memset(buffer, 0, sizeof(buffer));
130 rc = recvfrom(sockfd, buffer, sizeof(buffer),
131 0, (struct sockaddr *)&from,
132 (socklen_t *)&fromlen);
134 perror("recvfrom()");
140 if (strncmp(str, buffer, strlen(str)) != 0) {
141 fprintf(stderr, "expected string mismatch!\n");
144 } else { /* timeout */
145 fprintf(stderr, "timeout!\n");
154 static int remote_tst(int tc, char *mnt);
155 static int mmap_run(char *host, int tc)
158 char nodearg[256], command[256];
168 rc = remote_tst(tc, dir2);
170 sprintf(nodearg, "-w %s", node);
171 sprintf(command, "%s -d %s -n %s -c %d",
172 mmap_sanity, dir, host, tc);
173 rc = execlp("pdsh", "pdsh", "-S", nodearg, command, NULL);
180 static int mmap_initialize(char *myself, int tc)
182 char buf[1024], *file;
183 int fdr, fdw, count, rc = 0;
185 page_size = sysconf(_SC_PAGESIZE);
186 if (page_size == -1) {
187 perror("sysconf(_SC_PAGESIZE)");
193 /* copy myself to lustre for another client */
194 fdr = open(myself, O_RDONLY);
199 file = strrchr(myself, '/');
201 fprintf(stderr, "can't get test filename\n");
206 sprintf(mmap_sanity, "%s/%s", dir, file);
208 fdw = open(mmap_sanity, O_CREAT|O_WRONLY, 0777);
214 while ((count = read(fdr, buf, sizeof(buf))) != 0) {
222 writes = write(fdw, buf, count);
223 if (writes != count) {
234 static void mmap_finalize(int tc)
241 /* basic mmap operation on single node */
242 static int mmap_tst1(char *mnt)
244 char *ptr, mmap_file[256];
245 int i, j, region, fd, rc = 0;
247 region = page_size * 10;
248 sprintf(mmap_file, "%s/%s", mnt, "mmap_file1");
250 if (unlink(mmap_file) && errno != ENOENT) {
255 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
260 ftruncate(fd, region);
262 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
263 if (ptr == MAP_FAILED) {
268 memset(ptr, 'a', region);
270 /* mem write then sync */
271 for (i = 0; i < 5; i++) {
272 for (j = 0; j < region; j += page_size)
284 /* MAP_PRIVATE create a copy-on-write mmap */
285 static int mmap_tst2(char *mnt)
287 char *ptr, mmap_file[256], buf[256];
290 sprintf(mmap_file, "%s/%s", mnt, "mmap_file2");
292 if (unlink(mmap_file) && errno != ENOENT) {
297 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
302 ftruncate(fd, page_size);
304 ptr = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
305 if (ptr == MAP_FAILED) {
310 memcpy(ptr, "blah", strlen("blah"));
312 munmap(ptr, page_size);
318 fd = open(mmap_file, O_RDONLY);
323 rc = read(fd, buf, sizeof(buf));
331 if (strncmp("blah", buf, strlen("blah")) == 0) {
332 fprintf(stderr, "mmap write back with MAP_PRIVATE!\n");
340 /* cocurrent mmap operations on two nodes */
341 static int mmap_tst3(char *mnt)
343 char *ptr, mmap_file[256], host[256];
344 int region, fd, rc = 0;
346 region = page_size * 100;
347 sprintf(mmap_file, "%s/%s", mnt, "mmap_file3");
349 if (unlink(mmap_file) && errno != ENOENT) {
354 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
359 ftruncate(fd, region);
361 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
362 if (ptr == MAP_FAILED) {
368 if (gethostname(host, sizeof(host))) {
369 perror("gethostname()");
374 rc = mmap_run(host, 3);
378 rc = mmap_wait("mmap done", 10);
379 memset(ptr, 'a', region);
381 sleep(2); /* wait for remote test finish */
390 static int remote_tst3(char *mnt)
392 char *ptr, mmap_file[256];
393 int region, fd, rc = 0;
395 region = page_size * 100;
396 sprintf(mmap_file, "%s/%s", mnt, "mmap_file3");
398 fd = open(mmap_file, O_RDWR, 0600);
404 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
405 if (ptr == MAP_FAILED) {
410 memset(ptr, 'b', region);
412 rc = mmap_notify(node, "mmap done", 1);
416 memset(ptr, 'c', region);
425 /* client1 write to file_4a from mmap()ed file_4b;
426 * client2 write to file_4b from mmap()ed file_4a. */
427 static int mmap_tst4(char *mnt)
429 char *ptr, filea[256], fileb[256], host[256];
430 int region, fdr, fdw, rc = 0;
432 region = page_size * 100;
433 sprintf(filea, "%s/%s", mnt, "mmap_file_4a");
434 sprintf(fileb, "%s/%s", mnt, "mmap_file_4b");
436 if (unlink(filea) && errno != ENOENT) {
440 if (unlink(fileb) && errno != ENOENT) {
446 fdr = open(fileb, O_CREAT|O_RDWR, 0600);
451 ftruncate(fdr, region);
452 fdw = open(filea, O_CREAT|O_RDWR, 0600);
458 ftruncate(fdw, region);
460 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fdr, 0);
461 if (ptr == MAP_FAILED) {
467 if (gethostname(host, sizeof(host))) {
468 perror("gethostname()");
473 rc = mmap_run(host, 4);
477 rc = mmap_wait("mmap done", 10);
481 memset(ptr, '1', region);
483 rc = write(fdw, ptr, region);
490 sleep(2); /* wait for remote test finish */
503 static int remote_tst4(char *mnt)
505 char *ptr, filea[256], fileb[256];
506 int region, fdr, fdw, rc = 0;
508 region = page_size * 100;
509 sprintf(filea, "%s/%s", mnt, "mmap_file_4a");
510 sprintf(fileb, "%s/%s", mnt, "mmap_file_4b");
513 fdr = open(filea, O_RDWR, 0600);
518 fdw = open(fileb, O_RDWR, 0600);
525 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fdr, 0);
526 if (ptr == MAP_FAILED) {
532 rc = mmap_notify(node, "mmap done", 1);
536 memset(ptr, '2', region);
538 rc = write(fdw, ptr, region);
555 static int remote_tst(int tc, char *mnt)
560 rc = remote_tst3(mnt);
563 rc = remote_tst4(mnt);
568 fprintf(stderr, "wrong test case number %d\n", tc);
576 int tc; /* test case number */
577 char *desc; /* test description */
578 int (* test_fn)(char *mnt); /* test function */
579 int node_cnt; /* node count */
582 struct test_case tests[] = {
583 { 1, "mmap test1: basic mmap operation", mmap_tst1, 1 },
584 { 2, "mmap test2: MAP_PRIVATE not write back", mmap_tst2, 1 },
585 { 3, "mmap test3: cocurrent mmap ops on two nodes", mmap_tst3, 2 },
586 { 4, "mmap test4: c1 write to f1 from mmaped f2, "
587 "c2 write to f1 from mmaped f1", mmap_tst4, 2 },
591 int main(int argc, char **argv)
594 struct test_case *test;
595 int c, rc = 0, tc = 0;
598 c = getopt(argc, argv, "d:n:c:m:");
624 if (dir2 != NULL && node != NULL)
627 if (mmap_initialize(argv[0], tc) != 0) {
628 fprintf(stderr, "mmap_initialize failed!\n");
633 rc = remote_tst(tc, dir);
637 for (test = tests; test->tc; test++) {
640 if (test->node_cnt == 1 || node != NULL || dir2 != NULL) {
641 rc = test->test_fn(dir);
642 rs = rc ? "fail" : "pass";
644 fprintf(stderr, "%s (%s)\n", test->desc, rs);