+/* 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;
+}
+