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), 0,
131 (struct sockaddr *)&from, &fromlen);
133 perror("recvfrom()");
139 if (strncmp(str, buffer, strlen(str)) != 0) {
140 fprintf(stderr, "expected string mismatch!\n");
143 } else { /* timeout */
144 fprintf(stderr, "timeout!\n");
153 static int remote_tst(int tc, char *mnt);
154 static int mmap_run(char *host, int tc)
157 char nodearg[256], command[256];
167 rc = remote_tst(tc, dir2);
169 sprintf(nodearg, "-w %s", node);
170 sprintf(command, "%s -d %s -n %s -c %d",
171 mmap_sanity, dir, host, tc);
172 rc = execlp("pdsh", "pdsh", "-S", nodearg, command, NULL);
179 static int mmap_initialize(char *myself, int tc)
181 char buf[1024], *file;
182 int fdr, fdw, count, rc = 0;
184 page_size = sysconf(_SC_PAGESIZE);
185 if (page_size == -1) {
186 perror("sysconf(_SC_PAGESIZE)");
192 /* copy myself to lustre for another client */
193 fdr = open(myself, O_RDONLY);
198 file = strrchr(myself, '/');
200 fprintf(stderr, "can't get test filename\n");
205 sprintf(mmap_sanity, "%s/%s", dir, file);
207 fdw = open(mmap_sanity, O_CREAT|O_WRONLY, 0777);
213 while ((count = read(fdr, buf, sizeof(buf))) != 0) {
221 writes = write(fdw, buf, count);
222 if (writes != count) {
233 static void mmap_finalize(int tc)
240 /* basic mmap operation on single node */
241 static int mmap_tst1(char *mnt)
243 char *ptr, mmap_file[256];
244 int i, j, region, fd, rc = 0;
246 region = page_size * 10;
247 sprintf(mmap_file, "%s/%s", mnt, "mmap_file1");
249 if (unlink(mmap_file) && errno != ENOENT) {
254 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
259 ftruncate(fd, region);
261 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
262 if (ptr == MAP_FAILED) {
267 memset(ptr, 'a', region);
269 /* mem write then sync */
270 for (i = 0; i < 5; i++) {
271 for (j = 0; j < region; j += page_size)
283 /* MAP_PRIVATE create a copy-on-write mmap */
284 static int mmap_tst2(char *mnt)
286 char *ptr, mmap_file[256], buf[256];
289 sprintf(mmap_file, "%s/%s", mnt, "mmap_file2");
291 if (unlink(mmap_file) && errno != ENOENT) {
296 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
301 ftruncate(fd, page_size);
303 ptr = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
304 if (ptr == MAP_FAILED) {
309 memcpy(ptr, "blah", strlen("blah"));
311 munmap(ptr, page_size);
317 fd = open(mmap_file, O_RDONLY);
322 rc = read(fd, buf, sizeof(buf));
330 if (strncmp("blah", buf, strlen("blah")) == 0) {
331 fprintf(stderr, "mmap write back with MAP_PRIVATE!\n");
339 /* cocurrent mmap operations on two nodes */
340 static int mmap_tst3(char *mnt)
342 char *ptr, mmap_file[256], host[256];
343 int region, fd, rc = 0;
345 region = page_size * 100;
346 sprintf(mmap_file, "%s/%s", mnt, "mmap_file3");
348 if (unlink(mmap_file) && errno != ENOENT) {
353 fd = open(mmap_file, O_CREAT|O_RDWR, 0600);
358 ftruncate(fd, region);
360 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
361 if (ptr == MAP_FAILED) {
367 if (gethostname(host, sizeof(host))) {
368 perror("gethostname()");
373 rc = mmap_run(host, 3);
377 rc = mmap_wait("mmap done", 10);
378 memset(ptr, 'a', region);
380 sleep(2); /* wait for remote test finish */
389 static int remote_tst3(char *mnt)
391 char *ptr, mmap_file[256];
392 int region, fd, rc = 0;
394 region = page_size * 100;
395 sprintf(mmap_file, "%s/%s", mnt, "mmap_file3");
397 fd = open(mmap_file, O_RDWR, 0600);
403 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
404 if (ptr == MAP_FAILED) {
409 memset(ptr, 'b', region);
411 rc = mmap_notify(node, "mmap done", 1);
415 memset(ptr, 'c', region);
424 /* client1 write to file_4a from mmap()ed file_4b;
425 * client2 write to file_4b from mmap()ed file_4a. */
426 static int mmap_tst4(char *mnt)
428 char *ptr, filea[256], fileb[256], host[256];
429 int region, fdr, fdw, rc = 0;
431 region = page_size * 100;
432 sprintf(filea, "%s/%s", mnt, "mmap_file_4a");
433 sprintf(fileb, "%s/%s", mnt, "mmap_file_4b");
435 if (unlink(filea) && errno != ENOENT) {
439 if (unlink(fileb) && errno != ENOENT) {
445 fdr = open(fileb, O_CREAT|O_RDWR, 0600);
450 ftruncate(fdr, region);
451 fdw = open(filea, O_CREAT|O_RDWR, 0600);
457 ftruncate(fdw, region);
459 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fdr, 0);
460 if (ptr == MAP_FAILED) {
466 if (gethostname(host, sizeof(host))) {
467 perror("gethostname()");
472 rc = mmap_run(host, 4);
476 rc = mmap_wait("mmap done", 10);
480 memset(ptr, '1', region);
482 rc = write(fdw, ptr, region);
489 sleep(2); /* wait for remote test finish */
502 static int remote_tst4(char *mnt)
504 char *ptr, filea[256], fileb[256];
505 int region, fdr, fdw, rc = 0;
507 region = page_size * 100;
508 sprintf(filea, "%s/%s", mnt, "mmap_file_4a");
509 sprintf(fileb, "%s/%s", mnt, "mmap_file_4b");
512 fdr = open(filea, O_RDWR, 0600);
517 fdw = open(fileb, O_RDWR, 0600);
524 ptr = mmap(NULL, region, PROT_READ|PROT_WRITE, MAP_SHARED, fdr, 0);
525 if (ptr == MAP_FAILED) {
531 rc = mmap_notify(node, "mmap done", 1);
535 memset(ptr, '2', region);
537 rc = write(fdw, ptr, region);
554 static int remote_tst(int tc, char *mnt)
559 rc = remote_tst3(mnt);
562 rc = remote_tst4(mnt);
567 fprintf(stderr, "wrong test case number %d\n", tc);
575 int tc; /* test case number */
576 char *desc; /* test description */
577 int (* test_fn)(char *mnt); /* test function */
578 int node_cnt; /* node count */
581 struct test_case tests[] = {
582 { 1, "mmap test1: basic mmap operation", mmap_tst1, 1 },
583 { 2, "mmap test2: MAP_PRIVATE not write back", mmap_tst2, 1 },
584 { 3, "mmap test3: cocurrent mmap ops on two nodes", mmap_tst3, 2 },
585 { 4, "mmap test4: c1 write to f1 from mmaped f2, "
586 "c2 write to f1 from mmaped f1", mmap_tst4, 2 },
590 int main(int argc, char **argv)
593 struct test_case *test;
594 int c, rc = 0, tc = 0;
597 c = getopt(argc, argv, "d:n:c:m:");
623 if (dir2 != NULL && node != NULL)
626 if (mmap_initialize(argv[0], tc) != 0) {
627 fprintf(stderr, "mmap_initialize failed!\n");
632 rc = remote_tst(tc, dir);
636 for (test = tests; test->tc; test++) {
639 if (test->node_cnt == 1 || node != NULL || dir2 != NULL) {
640 rc = test->test_fn(dir);
641 rs = rc ? "fail" : "pass";
643 fprintf(stderr, "%s (%s)\n", test->desc, rs);