14 * Usage: rw_seq_cst_vs_drop_caches [-m] /mnt/lustre/file0 /mnt/lustre2/file0
16 * Race reads of the same file on two client mounts vs writes and drop
17 * caches to detect sequential consistency violations. Run
18 * indefinately. all abort() if a consistency violation is found in
19 * which case the wait status ($?) will be 134.
22 int mmap_mode; /* -m flag */
24 static void usage(void)
27 "%s: rw_seq_cst_vs_drop_caches [-m] /mnt/lustre/file0 /mnt/lustre2/file0\n"
28 " -m : use mmap to read/write file\n", __func__);
31 #define handle_error(msg) \
32 do { perror(msg); exit(EXIT_FAILURE); } while (0)
34 static int fd[2] = { -1, -1 };
35 /* u_max is total number of writes, which are time consumg because they are
36 * contending with constant reads
38 static uint64_t u, u_max = UINT64_MAX / 2;
42 static void *access_thread_start(void *unused)
49 ptr2 = mmap(NULL, sizeof(v[1]), PROT_READ,
50 MAP_PRIVATE | MAP_POPULATE, fd[1], 0);
51 if (ptr2 == MAP_FAILED)
56 for (i = 0; i < 2; i++) {
58 memcpy(&v[i], i == 0 ? ptr : ptr2,
61 rc = pread(fd[i], &v[i], sizeof(v[i]), 0);
62 if (rc < 0 || rc != sizeof(v[i]))
63 handle_error("pread");
66 } while (v[0] <= v[1]);
68 fprintf(stderr, "error: u = %"PRIu64", v = %"PRIu64", %"PRIu64"\n",
72 munmap(ptr2, sizeof(v[i]));
76 static char stderr_buf[4096];
78 int main(int argc, char *argv[])
80 int drop_caches_fd = -1;
81 pthread_t access_thread;
86 setvbuf(stderr, stderr_buf, _IOLBF, sizeof(stderr_buf));
88 while ((ch = getopt(argc, argv, "m")) >= 0) {
107 drop_caches_fd = open("/proc/sys/vm/drop_caches", O_WRONLY);
108 assert(!(drop_caches_fd < 0));
110 for (i = 0; i < 2; i++) {
111 fd[i] = open(argv[i], O_RDWR|O_CREAT|O_TRUNC, 0666);
113 handle_error("open");
115 rc = fstat(fd[i], &st[i]);
117 handle_error("fstat");
120 /* file0 and file1 should be the same file on two different
121 * client mount points. */
122 if (st[0].st_dev != st[1].st_dev ||
123 st[0].st_ino != st[1].st_ino) {
124 fprintf(stderr, "file mismatch\n");
129 if (ftruncate(fd[0], sizeof(u)) < 0)
130 handle_error("ftruncate");
132 ptr = mmap(NULL, sizeof(u), PROT_READ|PROT_WRITE, MAP_SHARED,
134 if (ptr == MAP_FAILED)
135 handle_error("mmap");
136 memcpy(ptr, &u, sizeof(u));
138 rc = pwrite(fd[0], &u, sizeof(u), 0);
139 if (rc < 0 || rc != sizeof(u))
140 handle_error("pwrite");
143 rc = pthread_create(&access_thread, NULL, &access_thread_start, NULL);
145 handle_error("pthread_create");
147 for (u = 1; u <= u_max; u++) {
149 memcpy(ptr, &u, sizeof(u));
151 rc = pwrite(fd[0], &u, sizeof(u), 0);
152 if (rc < 0 || rc != sizeof(u))
153 handle_error("pwrite");
156 rc = write(drop_caches_fd, "3\n", 2);
157 if (rc < 0 || rc != 2)
158 handle_error("drop caches");
161 rc = pthread_cancel(access_thread);
163 handle_error("pthread_cancel");
165 rc = pthread_join(access_thread, NULL);
167 handle_error("pthread_join");
170 munmap(ptr, sizeof(u));