4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
24 * Copyright 2016 Cray Inc. All rights reserved.
25 * Authors: Patrick Farrell, Frank Zago
27 * A few portions are extracted from llapi_layout_test.c
29 * The purpose of this test is to exercise the lockahead advice of ladvise.
31 * The program will exit as soon as a test fails.
38 #include <sys/types.h>
44 #include <lustre/lustreapi.h>
45 #include <linux/lustre/lustre_idl.h>
47 #define ERROR(fmt, ...) \
48 fprintf(stderr, "%s: %s:%d: %s: " fmt "\n", \
49 program_invocation_short_name, __FILE__, __LINE__, \
50 __func__, ## __VA_ARGS__);
52 #define DIE(fmt, ...) \
54 ERROR(fmt, ## __VA_ARGS__); \
58 #define ASSERTF(cond, fmt, ...) \
61 DIE("assertion '%s' failed: "fmt, \
62 #cond, ## __VA_ARGS__); \
65 #define PERFORM(testfn) \
68 fprintf(stderr, "Starting test " #testfn " at %lld\n", \
69 (unsigned long long)time(NULL)); \
71 fprintf(stderr, "Finishing test " #testfn " at %lld\n", \
72 (unsigned long long)time(NULL)); \
75 /* Name of file/directory. Will be set once and will not change. */
76 static char mainpath[PATH_MAX];
77 /* Path to same file/directory on second mount */
78 static char mainpath2[PATH_MAX];
79 static char *mainfile;
81 static char fsmountdir[PATH_MAX]; /* Lustre mountpoint */
82 static char *lustre_dir; /* Test directory inside Lustre */
83 static char *lustre_dir2; /* Same dir but on second mountpoint */
84 static int single_test; /* Number of a single test to execute*/
86 /* Cleanup our test file. */
87 static void cleanup(void)
92 /* Trivial helper for one advice */
93 void setup_ladvise_lockahead(struct llapi_lu_ladvise *advice, int mode,
94 int flags, size_t start, size_t end, bool async)
96 advice->lla_advice = LU_LADVISE_LOCKAHEAD;
97 advice->lla_lockahead_mode = mode;
99 advice->lla_peradvice_flags = flags | LF_ASYNC;
101 advice->lla_peradvice_flags = flags;
102 advice->lla_start = start;
103 advice->lla_end = end;
104 advice->lla_value3 = 0;
105 advice->lla_value4 = 0;
108 /* Test valid single lock ahead request */
109 static int test10(void)
111 struct llapi_lu_ladvise advice;
114 size_t write_size = 1024 * 1024;
116 char buf[write_size];
118 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
119 ASSERTF(fd >= 0, "open failed for '%s': %s",
120 mainpath, strerror(errno));
122 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
123 write_size - 1, true);
125 /* Manually set the result so we can verify it's being modified */
126 advice.lla_lockahead_result = 345678;
128 rc = llapi_ladvise(fd, 0, count, &advice);
130 "cannot lockahead '%s': %s", mainpath, strerror(errno));
131 ASSERTF(advice.lla_lockahead_result == 0,
132 "unexpected extent result: %d",
133 advice.lla_lockahead_result);
135 memset(buf, 0xaa, write_size);
136 rc = write(fd, buf, write_size);
137 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
138 mainpath, strerror(errno));
146 /* Get lock, wait until lock is taken */
147 static int test11(void)
149 struct llapi_lu_ladvise advice;
152 size_t write_size = 1024 * 1024;
154 char buf[write_size];
156 int enqueue_requests = 0;
158 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
159 ASSERTF(fd >= 0, "open failed for '%s': %s",
160 mainpath, strerror(errno));
162 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
163 write_size - 1, true);
165 /* Manually set the result so we can verify it's being modified */
166 advice.lla_lockahead_result = 345678;
168 rc = llapi_ladvise(fd, 0, count, &advice);
170 "cannot lockahead '%s': %s", mainpath, strerror(errno));
171 ASSERTF(advice.lla_lockahead_result == 0,
172 "unexpected extent result: %d",
173 advice.lla_lockahead_result);
177 /* Ask again until we get the lock (status 1). */
178 for (i = 1; i < 100; i++) {
179 usleep(100000); /* 0.1 second */
180 advice.lla_lockahead_result = 456789;
181 rc = llapi_ladvise(fd, 0, count, &advice);
182 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
183 mainpath, strerror(errno));
185 if (advice.lla_lockahead_result > 0)
191 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
192 "unexpected extent result: %d",
193 advice.lla_lockahead_result);
195 /* Again. This time it is always there. */
196 for (i = 0; i < 100; i++) {
197 advice.lla_lockahead_result = 456789;
198 rc = llapi_ladvise(fd, 0, count, &advice);
199 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
200 mainpath, strerror(errno));
201 ASSERTF(advice.lla_lockahead_result > 0,
202 "unexpected extent result: %d",
203 advice.lla_lockahead_result);
206 memset(buf, 0xaa, write_size);
207 rc = write(fd, buf, write_size);
208 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
209 mainpath, strerror(errno));
213 return enqueue_requests;
216 /* Test with several times the same extent */
217 static int test12(void)
219 struct llapi_lu_ladvise *advice;
220 const int count = 10;
222 size_t write_size = 1024 * 1024;
224 char buf[write_size];
226 int expected_lock_count = 0;
228 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
229 ASSERTF(fd >= 0, "open failed for '%s': %s",
230 mainpath, strerror(errno));
232 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
234 for (i = 0; i < count; i++) {
235 setup_ladvise_lockahead(&(advice[i]), MODE_WRITE_USER, 0, 0,
236 write_size - 1, true);
237 advice[i].lla_lockahead_result = 98674;
240 rc = llapi_ladvise(fd, 0, count, advice);
242 "cannot lockahead '%s': %s", mainpath, strerror(errno));
243 for (i = 0; i < count; i++) {
244 ASSERTF(advice[i].lla_lockahead_result >= 0,
245 "unexpected extent result for extent %d: %d",
246 i, advice[i].lla_lockahead_result);
248 /* Since all the requests are for the same extent, we should only have
249 * one lock at the end. */
250 expected_lock_count = 1;
252 /* Ask again until we get the locks. */
253 for (i = 1; i < 100; i++) {
254 usleep(100000); /* 0.1 second */
255 advice[count-1].lla_lockahead_result = 456789;
256 rc = llapi_ladvise(fd, 0, count, advice);
257 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
258 mainpath, strerror(errno));
260 if (advice[count-1].lla_lockahead_result > 0)
264 ASSERTF(advice[count-1].lla_lockahead_result == LLA_RESULT_SAME,
265 "unexpected extent result: %d",
266 advice[count-1].lla_lockahead_result);
268 memset(buf, 0xaa, write_size);
269 rc = write(fd, buf, write_size);
270 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
271 mainpath, strerror(errno));
276 return expected_lock_count;
279 /* Grow a lock forward */
280 static int test13(void)
282 struct llapi_lu_ladvise *advice = NULL;
285 size_t write_size = 1024 * 1024;
287 char buf[write_size];
289 int expected_lock_count = 0;
291 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
292 ASSERTF(fd >= 0, "open failed for '%s': %s",
293 mainpath, strerror(errno));
295 for (i = 0; i < 100; i++) {
298 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
299 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0,
300 i * write_size, (i+1)*write_size - 1,
302 advice[0].lla_lockahead_result = 98674;
304 rc = llapi_ladvise(fd, 0, count, advice);
305 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
310 ASSERTF(advice[0].lla_lockahead_result >= 0,
311 "unexpected extent result for extent %d: %d",
312 i, advice[0].lla_lockahead_result);
314 expected_lock_count++;
317 /* Ask again until we get the lock. */
318 for (i = 1; i < 100; i++) {
319 usleep(100000); /* 0.1 second */
320 advice[0].lla_lockahead_result = 456789;
321 rc = llapi_ladvise(fd, 0, count, advice);
322 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
323 mainpath, strerror(errno));
325 if (advice[0].lla_lockahead_result > 0)
329 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
330 "unexpected extent result: %d",
331 advice[0].lla_lockahead_result);
335 memset(buf, 0xaa, write_size);
336 rc = write(fd, buf, write_size);
337 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
338 mainpath, strerror(errno));
342 return expected_lock_count;
345 /* Grow a lock backward */
346 static int test14(void)
348 struct llapi_lu_ladvise *advice = NULL;
351 size_t write_size = 1024 * 1024;
353 char buf[write_size];
355 const int num_blocks = 100;
356 int expected_lock_count = 0;
358 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
359 ASSERTF(fd >= 0, "open failed for '%s': %s",
360 mainpath, strerror(errno));
362 for (i = 0; i < num_blocks; i++) {
363 size_t start = (num_blocks - i - 1) * write_size;
364 size_t end = (num_blocks - i) * write_size - 1;
368 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
369 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
371 advice[0].lla_lockahead_result = 98674;
373 rc = llapi_ladvise(fd, 0, count, advice);
374 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
379 ASSERTF(advice[0].lla_lockahead_result >= 0,
380 "unexpected extent result for extent %d: %d",
381 i, advice[0].lla_lockahead_result);
383 expected_lock_count++;
386 /* Ask again until we get the lock. */
387 for (i = 1; i < 100; i++) {
388 usleep(100000); /* 0.1 second */
389 advice[0].lla_lockahead_result = 456789;
390 rc = llapi_ladvise(fd, 0, count, advice);
391 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
392 mainpath, strerror(errno));
394 if (advice[0].lla_lockahead_result > 0)
398 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
399 "unexpected extent result: %d",
400 advice[0].lla_lockahead_result);
404 memset(buf, 0xaa, write_size);
405 rc = write(fd, buf, write_size);
406 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
407 mainpath, strerror(errno));
411 return expected_lock_count;
414 /* Request many locks at 10MiB intervals */
415 static int test15(void)
417 struct llapi_lu_ladvise *advice;
420 size_t write_size = 1024 * 1024;
422 char buf[write_size];
424 int expected_lock_count = 0;
426 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
427 ASSERTF(fd >= 0, "open failed for '%s': %s",
428 mainpath, strerror(errno));
430 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
432 for (i = 0; i < 500; i++) {
433 /* The 'UL' designators are required to avoid undefined
434 * behavior which GCC turns in to an infinite loop */
435 __u64 start = i * 1024UL * 1024UL * 10UL;
436 __u64 end = start + 1;
438 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
441 advice[0].lla_lockahead_result = 345678;
443 rc = llapi_ladvise(fd, 0, count, advice);
445 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
446 mainpath, strerror(errno));
447 ASSERTF(advice[0].lla_lockahead_result >= 0,
448 "unexpected extent result for extent %d: %d",
449 i, advice[0].lla_lockahead_result);
450 expected_lock_count++;
453 /* Ask again until we get the lock. */
454 for (i = 1; i < 100; i++) {
455 usleep(100000); /* 0.1 second */
456 advice[0].lla_lockahead_result = 456789;
457 rc = llapi_ladvise(fd, 0, count, advice);
458 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
459 mainpath, strerror(errno));
461 if (advice[0].lla_lockahead_result > 0)
465 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
466 "unexpected extent result: %d",
467 advice[0].lla_lockahead_result);
469 memset(buf, 0xaa, write_size);
470 rc = write(fd, buf, write_size);
471 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
472 mainpath, strerror(errno));
473 /* The write should cancel the first lock (which was too small)
474 * and create one of its own, so the net effect on lock count is 0. */
480 /* We have to map our expected return in to the range of valid return
482 expected_lock_count = expected_lock_count/100;
484 return expected_lock_count;
487 /* Use lockahead to verify behavior of ladvise locknoexpand */
488 static int test16(void)
490 struct llapi_lu_ladvise *advice;
491 struct llapi_lu_ladvise *advice_noexpand;
494 size_t write_size = 1024 * 1024;
496 __u64 end = write_size - 1;
498 char buf[write_size];
499 int expected_lock_count = 0;
501 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
502 ASSERTF(fd >= 0, "open failed for '%s': %s",
503 mainpath, strerror(errno));
505 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
506 advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
508 /* First ask for a read lock, which will conflict with the write */
509 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, false);
510 advice[0].lla_lockahead_result = 345678;
511 rc = llapi_ladvise(fd, 0, count, advice);
512 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
513 mainpath, strerror(errno));
514 ASSERTF(advice[0].lla_lockahead_result == 0,
515 "unexpected extent result for extent: %d",
516 advice[0].lla_lockahead_result);
518 /* Use an async request to verify we got the read lock we asked for */
519 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, true);
520 advice[0].lla_lockahead_result = 345678;
521 rc = llapi_ladvise(fd, 0, count, advice);
522 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
523 mainpath, strerror(errno));
524 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
525 "unexpected extent result for extent: %d",
526 advice[0].lla_lockahead_result);
529 advice_noexpand[0].lla_advice = LU_LADVISE_LOCKNOEXPAND;
530 advice_noexpand[0].lla_peradvice_flags = 0;
531 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
533 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
534 mainpath, strerror(errno));
536 /* This write should generate a lock on exactly "write_size" bytes */
537 memset(buf, 0xaa, write_size);
538 rc = write(fd, buf, write_size);
539 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
540 mainpath, strerror(errno));
541 /* Write should create one LDLM lock */
542 expected_lock_count++;
544 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
546 advice[0].lla_lockahead_result = 345678;
548 rc = llapi_ladvise(fd, 0, count, advice);
550 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
551 mainpath, strerror(errno));
552 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
553 "unexpected extent result for extent: %d",
554 advice[0].lla_lockahead_result);
556 /* Now, disable locknoexpand and try writing again. */
557 advice_noexpand[0].lla_peradvice_flags = LF_UNSET;
558 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
560 /* This write should get an expanded lock */
561 memset(buf, 0xaa, write_size);
562 rc = write(fd, buf, write_size);
563 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
564 mainpath, strerror(errno));
565 /* Write should create one LDLM lock */
566 expected_lock_count++;
568 /* Verify it didn't get a lock on just the bytes it wrote.*/
569 usleep(100000); /* 0.1 second, plenty of time to get the lock */
571 start = start + write_size;
572 end = end + write_size;
573 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
575 advice[0].lla_lockahead_result = 345678;
577 rc = llapi_ladvise(fd, 0, count, advice);
579 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
580 mainpath, strerror(errno));
581 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
582 "unexpected extent result for extent %d",
583 advice[0].lla_lockahead_result);
589 return expected_lock_count;
592 /* Use lockahead to verify behavior of ladvise locknoexpand, with O_NONBLOCK.
593 * There should be no change in behavior. */
594 static int test17(void)
596 struct llapi_lu_ladvise *advice;
597 struct llapi_lu_ladvise *advice_noexpand;
600 size_t write_size = 1024 * 1024;
602 __u64 end = write_size - 1;
604 char buf[write_size];
605 int expected_lock_count = 0;
607 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC | O_NONBLOCK,
609 ASSERTF(fd >= 0, "open failed for '%s': %s",
610 mainpath, strerror(errno));
612 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
613 advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
615 /* First ask for a read lock, which will conflict with the write */
616 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, false);
617 advice[0].lla_lockahead_result = 345678;
618 rc = llapi_ladvise(fd, 0, count, advice);
619 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
620 mainpath, strerror(errno));
621 ASSERTF(advice[0].lla_lockahead_result == 0,
622 "unexpected extent result for extent: %d",
623 advice[0].lla_lockahead_result);
625 /* Use an async request to verify we got the read lock we asked for */
626 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, true);
627 advice[0].lla_lockahead_result = 345678;
628 rc = llapi_ladvise(fd, 0, count, advice);
629 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
630 mainpath, strerror(errno));
631 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
632 "unexpected extent result for extent: %d",
633 advice[0].lla_lockahead_result);
636 advice_noexpand[0].lla_advice = LU_LADVISE_LOCKNOEXPAND;
637 advice_noexpand[0].lla_peradvice_flags = 0;
638 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
640 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
641 mainpath, strerror(errno));
643 /* This write should generate a lock on exactly "write_size" bytes */
644 memset(buf, 0xaa, write_size);
645 rc = write(fd, buf, write_size);
646 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
647 mainpath, strerror(errno));
648 /* Write should create one LDLM lock */
649 expected_lock_count++;
651 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
653 advice[0].lla_lockahead_result = 345678;
655 rc = llapi_ladvise(fd, 0, count, advice);
657 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
658 mainpath, strerror(errno));
659 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
660 "unexpected extent result for extent: %d",
661 advice[0].lla_lockahead_result);
663 /* Now, disable locknoexpand and try writing again. */
664 advice_noexpand[0].lla_peradvice_flags = LF_UNSET;
665 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
667 /* This write should get an expanded lock */
668 memset(buf, 0xaa, write_size);
669 rc = write(fd, buf, write_size);
670 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
671 mainpath, strerror(errno));
672 /* Write should create one LDLM lock */
673 expected_lock_count++;
675 /* Verify it didn't get a lock on just the bytes it wrote.*/
676 usleep(100000); /* 0.1 second, plenty of time to get the lock */
678 start = start + write_size;
679 end = end + write_size;
680 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
682 advice[0].lla_lockahead_result = 345678;
684 rc = llapi_ladvise(fd, 0, count, advice);
686 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
687 mainpath, strerror(errno));
688 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
689 "unexpected extent result for extent %d",
690 advice[0].lla_lockahead_result);
696 return expected_lock_count;
699 /* Test overlapping requests */
700 static int test18(void)
702 struct llapi_lu_ladvise *advice;
707 int expected_lock_count = 0;
709 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
710 ASSERTF(fd >= 0, "open failed for '%s': %s",
711 mainpath, strerror(errno));
713 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
715 /* Overlapping locks - Should only end up with 1 */
716 for (i = 0; i < 10; i++) {
718 __u64 end = start + 4096;
720 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
723 advice[0].lla_lockahead_result = 345678;
725 rc = llapi_ladvise(fd, 0, count, advice);
727 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
728 mainpath, strerror(errno));
729 ASSERTF(advice[0].lla_lockahead_result >= 0,
730 "unexpected extent result for extent %d: %d",
731 i, advice[0].lla_lockahead_result);
733 expected_lock_count = 1;
735 /* Ask again until we get the lock. */
736 for (i = 1; i < 100; i++) {
737 usleep(100000); /* 0.1 second */
738 advice[0].lla_lockahead_result = 456789;
739 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, 0, 4096,
741 rc = llapi_ladvise(fd, 0, count, advice);
742 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
743 mainpath, strerror(errno));
745 if (advice[0].lla_lockahead_result > 0)
749 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
750 "unexpected extent result: %d",
751 advice[0].lla_lockahead_result);
757 return expected_lock_count;
760 /* Test that normal request blocks lock ahead requests */
761 static int test19(void)
763 struct llapi_lu_ladvise *advice;
766 size_t write_size = 1024 * 1024;
768 char buf[write_size];
770 int expected_lock_count = 0;
772 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
773 ASSERTF(fd >= 0, "open failed for '%s': %s",
774 mainpath, strerror(errno));
776 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
778 /* This should create a lock on the whole file, which will block lock
780 memset(buf, 0xaa, write_size);
781 rc = write(fd, buf, write_size);
782 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
783 mainpath, strerror(errno));
785 expected_lock_count = 1;
787 /* These should all be blocked. */
788 for (i = 0; i < 10; i++) {
789 __u64 start = i * 4096;
790 __u64 end = start + 4096;
792 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
795 advice[0].lla_lockahead_result = 345678;
797 rc = llapi_ladvise(fd, 0, count, advice);
799 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
800 mainpath, strerror(errno));
801 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
802 "unexpected extent result for extent %d: %d",
803 i, advice[0].lla_lockahead_result);
810 return expected_lock_count;
813 /* Test sync requests, and matching with async requests */
814 static int test20(void)
816 struct llapi_lu_ladvise advice;
819 size_t write_size = 1024 * 1024;
821 char buf[write_size];
823 int expected_lock_count = 1;
825 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
826 ASSERTF(fd >= 0, "open failed for '%s': %s",
827 mainpath, strerror(errno));
830 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
831 write_size - 1, true);
833 /* Manually set the result so we can verify it's being modified */
834 advice.lla_lockahead_result = 345678;
836 rc = llapi_ladvise(fd, 0, count, &advice);
838 "cannot lockahead '%s': %s", mainpath, strerror(errno));
839 ASSERTF(advice.lla_lockahead_result == 0,
840 "unexpected extent result: %d",
841 advice.lla_lockahead_result);
843 /* Ask again until we get the lock (status 1). */
844 for (i = 1; i < 100; i++) {
845 usleep(100000); /* 0.1 second */
846 advice.lla_lockahead_result = 456789;
847 rc = llapi_ladvise(fd, 0, count, &advice);
848 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
849 mainpath, strerror(errno));
851 if (advice.lla_lockahead_result > 0)
855 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
856 "unexpected extent result: %d",
857 advice.lla_lockahead_result);
859 /* Convert to a sync request on smaller range, should match and not
861 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
862 write_size - 1 - write_size/2, false);
864 advice.lla_lockahead_result = 456789;
865 rc = llapi_ladvise(fd, 0, count, &advice);
866 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
867 mainpath, strerror(errno));
868 /* Sync requests cannot give detailed results */
869 ASSERTF(advice.lla_lockahead_result == 0,
870 "unexpected extent result: %d",
871 advice.lla_lockahead_result);
873 /* Use an async request to test original lock is still present */
874 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
875 write_size - 1, true);
877 advice.lla_lockahead_result = 456789;
878 rc = llapi_ladvise(fd, 0, count, &advice);
879 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
880 mainpath, strerror(errno));
881 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
882 "unexpected extent result: %d",
883 advice.lla_lockahead_result);
885 memset(buf, 0xaa, write_size);
886 rc = write(fd, buf, write_size);
887 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
888 mainpath, strerror(errno));
892 return expected_lock_count;
895 /* Test sync requests, and conflict with async requests */
896 static int test21(void)
898 struct llapi_lu_ladvise advice;
901 size_t write_size = 1024 * 1024;
903 char buf[write_size];
905 int expected_lock_count = 1;
907 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
908 ASSERTF(fd >= 0, "open failed for '%s': %s",
909 mainpath, strerror(errno));
912 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
913 write_size - 1, true);
915 /* Manually set the result so we can verify it's being modified */
916 advice.lla_lockahead_result = 345678;
918 rc = llapi_ladvise(fd, 0, count, &advice);
920 "cannot lockahead '%s': %s", mainpath, strerror(errno));
921 ASSERTF(advice.lla_lockahead_result == 0,
922 "unexpected extent result: %d",
923 advice.lla_lockahead_result);
925 /* Ask again until we get the lock (status 1). */
926 for (i = 1; i < 100; i++) {
927 usleep(100000); /* 0.1 second */
928 advice.lla_lockahead_result = 456789;
929 rc = llapi_ladvise(fd, 0, count, &advice);
930 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
931 mainpath, strerror(errno));
933 if (advice.lla_lockahead_result > 0)
937 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
938 "unexpected extent result: %d",
939 advice.lla_lockahead_result);
941 /* Convert to a sync request on larger range, should cancel existing
943 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
944 write_size*2 - 1, false);
946 advice.lla_lockahead_result = 456789;
947 rc = llapi_ladvise(fd, 0, count, &advice);
948 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
949 mainpath, strerror(errno));
950 /* Sync requests cannot give detailed results */
951 ASSERTF(advice.lla_lockahead_result == 0,
952 "unexpected extent result: %d",
953 advice.lla_lockahead_result);
955 /* Use an async request to test new lock is there */
956 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
957 write_size*2 - 1, true);
959 advice.lla_lockahead_result = 456789;
960 rc = llapi_ladvise(fd, 0, count, &advice);
961 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
962 mainpath, strerror(errno));
963 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
964 "unexpected extent result: %d",
965 advice.lla_lockahead_result);
967 memset(buf, 0xaa, write_size);
968 rc = write(fd, buf, write_size);
969 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
970 mainpath, strerror(errno));
974 return expected_lock_count;
977 /* Test various valid and invalid inputs */
978 static int test22(void)
980 struct llapi_lu_ladvise *advice;
987 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
988 ASSERTF(fd >= 0, "open failed for '%s': %s",
989 mainpath, strerror(errno));
991 /* A valid async request first */
992 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
995 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
996 rc = llapi_ladvise(fd, 0, count, advice);
997 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
998 mainpath, strerror(errno));
1001 /* Valid request sync request */
1002 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1005 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, false);
1006 rc = llapi_ladvise(fd, 0, count, advice);
1007 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
1008 mainpath, strerror(errno));
1011 /* No actual block */
1012 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1015 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
1016 rc = llapi_ladvise(fd, 0, count, advice);
1017 ASSERTF(rc == -1 && errno == EINVAL,
1018 "unexpected return for no block lock: %d %s",
1019 rc, strerror(errno));
1022 /* end before start */
1023 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1024 start = 1024 * 1024;
1026 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
1027 rc = llapi_ladvise(fd, 0, count, advice);
1028 ASSERTF(rc == -1 && errno == EINVAL,
1029 "unexpected return for reversed block: %d %s",
1030 rc, strerror(errno));
1033 /* bogus lock mode - 0x65464 */
1034 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1037 setup_ladvise_lockahead(advice, 0x65464, 0, start, end, true);
1038 rc = llapi_ladvise(fd, 0, count, advice);
1039 ASSERTF(rc == -1 && errno == EINVAL,
1040 "unexpected return for bogus lock mode: %d %s",
1041 rc, strerror(errno));
1044 /* bogus flags, 0x80 */
1045 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1048 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0x80, start, end,
1050 rc = llapi_ladvise(fd, 0, count, advice);
1051 ASSERTF(rc == -1 && errno == EINVAL,
1052 "unexpected return for bogus flags: %u %d %s",
1053 0x80, rc, strerror(errno));
1056 /* bogus flags, 0xff - CEF_MASK */
1057 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1059 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xff, start, end,
1061 rc = llapi_ladvise(fd, 0, count, advice);
1062 ASSERTF(rc == -1 && errno == EINVAL,
1063 "unexpected return for bogus flags: %u %d %s",
1064 0xff, rc, strerror(errno));
1067 /* bogus flags, 0xffffffff */
1068 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1070 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xffffffff, start,
1072 rc = llapi_ladvise(fd, 0, count, advice);
1073 ASSERTF(rc == -1 && errno == EINVAL,
1074 "unexpected return for bogus flags: %u %d %s",
1075 0xffffffff, rc, strerror(errno));
1083 /* Do lockahead requests from two mount points & sanity check size
1085 * The key thing here is that client2 updates the size by writing, then asks
1086 * for another lock beyond that. That next lock is never used.
1087 * The bug (LU-11670) is that the glimpse for client1 will only check the
1088 * highest lock and miss the size update made by the lower lock.
1090 static int test23(void)
1092 struct llapi_lu_ladvise advice;
1093 size_t write_size = 1024 * 1024;
1094 char buf[write_size];
1095 const int count = 1;
1099 /* On second mount */
1104 fd = open(mainpath, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
1105 ASSERTF(fd >= 0, "open failed for '%s': %s",
1106 mainpath, strerror(errno));
1108 /* mainpath2 is a different Lustre mount */
1109 fd2 = open(mainpath2, O_RDWR, S_IRUSR | S_IWUSR);
1110 ASSERTF(fd2 >= 0, "open failed for '%s': %s",
1111 mainpath2, strerror(errno));
1113 /* Lock + write MiB 1 from second client */
1114 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
1115 write_size - 1, true);
1117 /* Manually set the result so we can verify it's being modified */
1118 advice.lla_lockahead_result = 345678;
1120 rc = llapi_ladvise(fd2, 0, count, &advice);
1122 "cannot lockahead '%s': %s", mainpath2, strerror(errno));
1123 ASSERTF(advice.lla_lockahead_result == 0,
1124 "unexpected extent result: %d",
1125 advice.lla_lockahead_result);
1127 /* Ask again until we get the lock (status 1). */
1128 for (i = 1; i < 100; i++) {
1129 usleep(100000); /* 0.1 second */
1130 advice.lla_lockahead_result = 456789;
1131 rc = llapi_ladvise(fd2, 0, count, &advice);
1132 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
1133 mainpath2, strerror(errno));
1135 if (advice.lla_lockahead_result > 0)
1139 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
1140 "unexpected extent result: %d",
1141 advice.lla_lockahead_result);
1143 rc = write(fd2, buf, write_size);
1144 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
1145 mainpath2, strerror(errno));
1147 /* Lock (but don't write) MiB 2 from second client */
1148 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, write_size,
1149 2*write_size - 1, true);
1151 /* Manually set the result so we can verify it's being modified */
1152 advice.lla_lockahead_result = 345678;
1154 rc = llapi_ladvise(fd2, 0, count, &advice);
1156 "cannot lockahead '%s': %s", mainpath2, strerror(errno));
1157 ASSERTF(advice.lla_lockahead_result == 0,
1158 "unexpected extent result: %d",
1159 advice.lla_lockahead_result);
1161 /* Ask again until we get the lock (status 1). */
1162 for (i = 1; i < 100; i++) {
1163 usleep(100000); /* 0.1 second */
1164 advice.lla_lockahead_result = 456789;
1165 rc = llapi_ladvise(fd2, 0, count, &advice);
1166 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
1167 mainpath2, strerror(errno));
1169 if (advice.lla_lockahead_result > 0)
1173 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
1174 "unexpected extent result: %d",
1175 advice.lla_lockahead_result);
1177 rc = fstat(fd, &sb);
1178 ASSERTF(!rc, "stat failed for '%s': %s",
1179 mainpath, strerror(errno));
1180 rc = fstat(fd2, &sb2);
1181 ASSERTF(!rc, "stat failed for '%s': %s",
1182 mainpath2, strerror(errno));
1184 ASSERTF(sb.st_size == sb2.st_size,
1185 "size on %s and %s differs: %lu vs %lu",
1186 mainpath, mainpath2, sb.st_size, sb2.st_size);
1188 ASSERTF(sb.st_size == write_size, "size %lu != bytes written (%lu)",
1189 sb.st_size, write_size);
1197 static void usage(char *prog)
1200 "Usage: %s [-d lustre_dir], [-D lustre_dir2] [-t test]\n",
1205 static void process_args(int argc, char *argv[])
1209 while ((c = getopt(argc, argv, "d:D:f:t:")) != -1) {
1215 lustre_dir = optarg;
1218 lustre_dir2 = optarg;
1221 single_test = atoi(optarg);
1225 fprintf(stderr, "Invalid option '%c'\n", optopt);
1232 int main(int argc, char *argv[])
1237 process_args(argc, argv);
1238 if (lustre_dir == NULL)
1239 lustre_dir = "/mnt/lustre";
1240 if (mainfile == NULL)
1241 mainfile = "lockahead_test_654";
1243 rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname);
1245 fprintf(stderr, "Error: '%s': not a Lustre filesystem\n",
1251 rc = llapi_search_mounts(lustre_dir2, 0, fsmountdir, fsname);
1254 "Error: '%s': not a Lustre filesystem\n",
1260 /* Play nice with Lustre test scripts. Non-line buffered output
1261 * stream under I/O redirection may appear incorrectly. */
1262 setvbuf(stdout, NULL, _IOLBF, 0);
1264 /* Create a test filename and reuse it. Remove possibly old files. */
1265 rc = snprintf(mainpath, sizeof(mainpath), "%s/%s", lustre_dir,
1267 ASSERTF(rc > 0 && rc < sizeof(mainpath), "invalid name for mainpath");
1270 rc = snprintf(mainpath2, sizeof(mainpath2), "%s/%s",
1271 lustre_dir2, mainfile);
1272 ASSERTF(rc > 0 && rc < sizeof(mainpath2),
1273 "invalid name for mainpath2");
1278 switch (single_test) {
1293 /* Some tests require a second mount point */
1296 /* When running all the test cases, we can't use the return
1297 * from the last test case, as it might be non-zero to return
1298 * info, rather than for an error. Test cases assert and exit
1299 * if an error occurs. */
1342 ASSERTF(lustre_dir2,
1343 "must provide second mount point for test 23");
1347 fprintf(stderr, "impossible value of single_test %d\n",