X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Ftests%2Flockahead_test.c;h=7fd180e1b09d833145b169b0c2591d3f3f9990d3;hp=11cb8432a50a416c3c4b4ad009988a47aa38cd71;hb=b3461d11dcb04670cc2e1bfbb99306cfd3f645ef;hpb=a8dcf372f430c308d3e96fb506563068d0a80c2d diff --git a/lustre/tests/lockahead_test.c b/lustre/tests/lockahead_test.c index 11cb843..7fd180e 100644 --- a/lustre/tests/lockahead_test.c +++ b/lustre/tests/lockahead_test.c @@ -70,15 +70,17 @@ rc = testfn(); \ fprintf(stderr, "Finishing test " #testfn " at %lld\n", \ (unsigned long long)time(NULL)); \ - cleanup(); \ } while (0) /* Name of file/directory. Will be set once and will not change. */ static char mainpath[PATH_MAX]; -static const char *mainfile = "lockahead_test_654"; +/* Path to same file/directory on second mount */ +static char mainpath2[PATH_MAX]; +static char *mainfile; static char fsmountdir[PATH_MAX]; /* Lustre mountpoint */ static char *lustre_dir; /* Test directory inside Lustre */ +static char *lustre_dir2; /* Same dir but on second mountpoint */ static int single_test; /* Number of a single test to execute*/ /* Cleanup our test file. */ @@ -427,7 +429,7 @@ static int test15(void) advice = malloc(sizeof(struct llapi_lu_ladvise)*count); - for (i = 0; i < 5000; i++) { + for (i = 0; i < 500; i++) { /* The 'UL' designators are required to avoid undefined * behavior which GCC turns in to an infinite loop */ __u64 start = i * 1024UL * 1024UL * 10UL; @@ -477,7 +479,7 @@ static int test15(void) /* We have to map our expected return in to the range of valid return * codes, 0-255. */ - expected_lock_count = expected_lock_count/1000; + expected_lock_count = expected_lock_count/100; return expected_lock_count; } @@ -1078,9 +1080,125 @@ static int test22(void) return 0; } +/* Do lockahead requests from two mount points & sanity check size + * + * The key thing here is that client2 updates the size by writing, then asks + * for another lock beyond that. That next lock is never used. + * The bug (LU-11670) is that the glimpse for client1 will only check the + * highest lock and miss the size update made by the lower lock. + */ +static int test23(void) +{ + struct llapi_lu_ladvise advice; + size_t write_size = 1024 * 1024; + char buf[write_size]; + const int count = 1; + struct stat sb; + struct stat sb2; + int fd; + /* On second mount */ + int fd2; + int rc; + int i; + + fd = open(mainpath, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + ASSERTF(fd >= 0, "open failed for '%s': %s", + mainpath, strerror(errno)); + + /* mainpath2 is a different Lustre mount */ + fd2 = open(mainpath2, O_RDWR, S_IRUSR | S_IWUSR); + ASSERTF(fd2 >= 0, "open failed for '%s': %s", + mainpath2, strerror(errno)); + + /* Lock + write MiB 1 from second client */ + setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0, + write_size - 1, true); + + /* Manually set the result so we can verify it's being modified */ + advice.lla_lockahead_result = 345678; + + rc = llapi_ladvise(fd2, 0, count, &advice); + ASSERTF(rc == 0, + "cannot lockahead '%s': %s", mainpath2, strerror(errno)); + ASSERTF(advice.lla_lockahead_result == 0, + "unexpected extent result: %d", + advice.lla_lockahead_result); + + /* Ask again until we get the lock (status 1). */ + for (i = 1; i < 100; i++) { + usleep(100000); /* 0.1 second */ + advice.lla_lockahead_result = 456789; + rc = llapi_ladvise(fd2, 0, count, &advice); + ASSERTF(rc == 0, "cannot lockahead '%s': %s", + mainpath2, strerror(errno)); + + if (advice.lla_lockahead_result > 0) + break; + } + + ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME, + "unexpected extent result: %d", + advice.lla_lockahead_result); + + rc = write(fd2, buf, write_size); + ASSERTF(rc == sizeof(buf), "write failed for '%s': %s", + mainpath2, strerror(errno)); + + /* Lock (but don't write) MiB 2 from second client */ + setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, write_size, + 2*write_size - 1, true); + + /* Manually set the result so we can verify it's being modified */ + advice.lla_lockahead_result = 345678; + + rc = llapi_ladvise(fd2, 0, count, &advice); + ASSERTF(rc == 0, + "cannot lockahead '%s': %s", mainpath2, strerror(errno)); + ASSERTF(advice.lla_lockahead_result == 0, + "unexpected extent result: %d", + advice.lla_lockahead_result); + + /* Ask again until we get the lock (status 1). */ + for (i = 1; i < 100; i++) { + usleep(100000); /* 0.1 second */ + advice.lla_lockahead_result = 456789; + rc = llapi_ladvise(fd2, 0, count, &advice); + ASSERTF(rc == 0, "cannot lockahead '%s': %s", + mainpath2, strerror(errno)); + + if (advice.lla_lockahead_result > 0) + break; + } + + ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME, + "unexpected extent result: %d", + advice.lla_lockahead_result); + + rc = fstat(fd, &sb); + ASSERTF(!rc, "stat failed for '%s': %s", + mainpath, strerror(errno)); + rc = fstat(fd2, &sb2); + ASSERTF(!rc, "stat failed for '%s': %s", + mainpath2, strerror(errno)); + + ASSERTF(sb.st_size == sb2.st_size, + "size on %s and %s differs: %lu vs %lu", + mainpath, mainpath2, sb.st_size, sb2.st_size); + + ASSERTF(sb.st_size == write_size, "size %lu != bytes written (%lu)", + sb.st_size, write_size); + + close(fd); + close(fd2); + + return 0; +} + static void usage(char *prog) { - fprintf(stderr, "Usage: %s [-d lustre_dir], [-t single_test]\n", prog); + fprintf(stderr, + "Usage: %s [-d lustre_dir], [-D lustre_dir2] [-t test]\n", + prog); exit(-1); } @@ -1088,11 +1206,17 @@ static void process_args(int argc, char *argv[]) { int c; - while ((c = getopt(argc, argv, "d:t:")) != -1) { + while ((c = getopt(argc, argv, "d:D:f:t:")) != -1) { switch (c) { + case 'f': + mainfile = optarg; + break; case 'd': lustre_dir = optarg; break; + case 'D': + lustre_dir2 = optarg; + break; case 't': single_test = atoi(optarg); break; @@ -1113,6 +1237,8 @@ int main(int argc, char *argv[]) process_args(argc, argv); if (lustre_dir == NULL) lustre_dir = "/mnt/lustre"; + if (mainfile == NULL) + mainfile = "lockahead_test_654"; rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname); if (rc != 0) { @@ -1121,6 +1247,16 @@ int main(int argc, char *argv[]) return -1; } + if (lustre_dir2) { + rc = llapi_search_mounts(lustre_dir2, 0, fsmountdir, fsname); + if (rc != 0) { + fprintf(stderr, + "Error: '%s': not a Lustre filesystem\n", + lustre_dir2); + return -1; + } + } + /* Play nice with Lustre test scripts. Non-line buffered output * stream under I/O redirection may appear incorrectly. */ setvbuf(stdout, NULL, _IOLBF, 0); @@ -1129,9 +1265,15 @@ int main(int argc, char *argv[]) rc = snprintf(mainpath, sizeof(mainpath), "%s/%s", lustre_dir, mainfile); ASSERTF(rc > 0 && rc < sizeof(mainpath), "invalid name for mainpath"); - cleanup(); - atexit(cleanup); + if (lustre_dir2) { + rc = snprintf(mainpath2, sizeof(mainpath2), "%s/%s", + lustre_dir2, mainfile); + ASSERTF(rc > 0 && rc < sizeof(mainpath2), + "invalid name for mainpath2"); + } + + cleanup(); switch (single_test) { case 0: @@ -1148,6 +1290,9 @@ int main(int argc, char *argv[]) PERFORM(test20); PERFORM(test21); PERFORM(test22); + /* Some tests require a second mount point */ + if (lustre_dir2) + PERFORM(test23); /* When running all the test cases, we can't use the return * from the last test case, as it might be non-zero to return * info, rather than for an error. Test cases assert and exit @@ -1193,6 +1338,11 @@ int main(int argc, char *argv[]) case 22: PERFORM(test22); break; + case 23: + ASSERTF(lustre_dir2, + "must provide second mount point for test 23"); + PERFORM(test23); + break; default: fprintf(stderr, "impossible value of single_test %d\n", single_test);