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)); \
76 /* Name of file/directory. Will be set once and will not change. */
77 static char mainpath[PATH_MAX];
78 static const char *mainfile = "lockahead_test_654";
80 static char fsmountdir[PATH_MAX]; /* Lustre mountpoint */
81 static char *lustre_dir; /* Test directory inside Lustre */
82 static int single_test; /* Number of a single test to execute*/
84 /* Cleanup our test file. */
85 static void cleanup(void)
90 /* Trivial helper for one advice */
91 void setup_ladvise_lockahead(struct llapi_lu_ladvise *advice, int mode,
92 int flags, size_t start, size_t end, bool async)
94 advice->lla_advice = LU_LADVISE_LOCKAHEAD;
95 advice->lla_lockahead_mode = mode;
97 advice->lla_peradvice_flags = flags | LF_ASYNC;
99 advice->lla_peradvice_flags = flags;
100 advice->lla_start = start;
101 advice->lla_end = end;
102 advice->lla_value3 = 0;
103 advice->lla_value4 = 0;
106 /* Test valid single lock ahead request */
107 static int test10(void)
109 struct llapi_lu_ladvise advice;
112 size_t write_size = 1024 * 1024;
114 char buf[write_size];
116 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
117 ASSERTF(fd >= 0, "open failed for '%s': %s",
118 mainpath, strerror(errno));
120 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
121 write_size - 1, true);
123 /* Manually set the result so we can verify it's being modified */
124 advice.lla_lockahead_result = 345678;
126 rc = llapi_ladvise(fd, 0, count, &advice);
128 "cannot lockahead '%s': %s", mainpath, strerror(errno));
129 ASSERTF(advice.lla_lockahead_result == 0,
130 "unexpected extent result: %d",
131 advice.lla_lockahead_result);
133 memset(buf, 0xaa, write_size);
134 rc = write(fd, buf, write_size);
135 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
136 mainpath, strerror(errno));
144 /* Get lock, wait until lock is taken */
145 static int test11(void)
147 struct llapi_lu_ladvise advice;
150 size_t write_size = 1024 * 1024;
152 char buf[write_size];
154 int enqueue_requests = 0;
156 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
157 ASSERTF(fd >= 0, "open failed for '%s': %s",
158 mainpath, strerror(errno));
160 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
161 write_size - 1, true);
163 /* Manually set the result so we can verify it's being modified */
164 advice.lla_lockahead_result = 345678;
166 rc = llapi_ladvise(fd, 0, count, &advice);
168 "cannot lockahead '%s': %s", mainpath, strerror(errno));
169 ASSERTF(advice.lla_lockahead_result == 0,
170 "unexpected extent result: %d",
171 advice.lla_lockahead_result);
175 /* Ask again until we get the lock (status 1). */
176 for (i = 1; i < 100; i++) {
177 usleep(100000); /* 0.1 second */
178 advice.lla_lockahead_result = 456789;
179 rc = llapi_ladvise(fd, 0, count, &advice);
180 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
181 mainpath, strerror(errno));
183 if (advice.lla_lockahead_result > 0)
189 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
190 "unexpected extent result: %d",
191 advice.lla_lockahead_result);
193 /* Again. This time it is always there. */
194 for (i = 0; i < 100; i++) {
195 advice.lla_lockahead_result = 456789;
196 rc = llapi_ladvise(fd, 0, count, &advice);
197 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
198 mainpath, strerror(errno));
199 ASSERTF(advice.lla_lockahead_result > 0,
200 "unexpected extent result: %d",
201 advice.lla_lockahead_result);
204 memset(buf, 0xaa, write_size);
205 rc = write(fd, buf, write_size);
206 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
207 mainpath, strerror(errno));
211 return enqueue_requests;
214 /* Test with several times the same extent */
215 static int test12(void)
217 struct llapi_lu_ladvise *advice;
218 const int count = 10;
220 size_t write_size = 1024 * 1024;
222 char buf[write_size];
224 int expected_lock_count = 0;
226 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
227 ASSERTF(fd >= 0, "open failed for '%s': %s",
228 mainpath, strerror(errno));
230 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
232 for (i = 0; i < count; i++) {
233 setup_ladvise_lockahead(&(advice[i]), MODE_WRITE_USER, 0, 0,
234 write_size - 1, true);
235 advice[i].lla_lockahead_result = 98674;
238 rc = llapi_ladvise(fd, 0, count, advice);
240 "cannot lockahead '%s': %s", mainpath, strerror(errno));
241 for (i = 0; i < count; i++) {
242 ASSERTF(advice[i].lla_lockahead_result >= 0,
243 "unexpected extent result for extent %d: %d",
244 i, advice[i].lla_lockahead_result);
246 /* Since all the requests are for the same extent, we should only have
247 * one lock at the end. */
248 expected_lock_count = 1;
250 /* Ask again until we get the locks. */
251 for (i = 1; i < 100; i++) {
252 usleep(100000); /* 0.1 second */
253 advice[count-1].lla_lockahead_result = 456789;
254 rc = llapi_ladvise(fd, 0, count, advice);
255 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
256 mainpath, strerror(errno));
258 if (advice[count-1].lla_lockahead_result > 0)
262 ASSERTF(advice[count-1].lla_lockahead_result == LLA_RESULT_SAME,
263 "unexpected extent result: %d",
264 advice[count-1].lla_lockahead_result);
266 memset(buf, 0xaa, write_size);
267 rc = write(fd, buf, write_size);
268 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
269 mainpath, strerror(errno));
274 return expected_lock_count;
277 /* Grow a lock forward */
278 static int test13(void)
280 struct llapi_lu_ladvise *advice = NULL;
283 size_t write_size = 1024 * 1024;
285 char buf[write_size];
287 int expected_lock_count = 0;
289 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
290 ASSERTF(fd >= 0, "open failed for '%s': %s",
291 mainpath, strerror(errno));
293 for (i = 0; i < 100; i++) {
296 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
297 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0,
298 i * write_size, (i+1)*write_size - 1,
300 advice[0].lla_lockahead_result = 98674;
302 rc = llapi_ladvise(fd, 0, count, advice);
303 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
308 ASSERTF(advice[0].lla_lockahead_result >= 0,
309 "unexpected extent result for extent %d: %d",
310 i, advice[0].lla_lockahead_result);
312 expected_lock_count++;
315 /* Ask again until we get the lock. */
316 for (i = 1; i < 100; i++) {
317 usleep(100000); /* 0.1 second */
318 advice[0].lla_lockahead_result = 456789;
319 rc = llapi_ladvise(fd, 0, count, advice);
320 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
321 mainpath, strerror(errno));
323 if (advice[0].lla_lockahead_result > 0)
327 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
328 "unexpected extent result: %d",
329 advice[0].lla_lockahead_result);
333 memset(buf, 0xaa, write_size);
334 rc = write(fd, buf, write_size);
335 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
336 mainpath, strerror(errno));
340 return expected_lock_count;
343 /* Grow a lock backward */
344 static int test14(void)
346 struct llapi_lu_ladvise *advice = NULL;
349 size_t write_size = 1024 * 1024;
351 char buf[write_size];
353 const int num_blocks = 100;
354 int expected_lock_count = 0;
356 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
357 ASSERTF(fd >= 0, "open failed for '%s': %s",
358 mainpath, strerror(errno));
360 for (i = 0; i < num_blocks; i++) {
361 size_t start = (num_blocks - i - 1) * write_size;
362 size_t end = (num_blocks - i) * write_size - 1;
366 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
367 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
369 advice[0].lla_lockahead_result = 98674;
371 rc = llapi_ladvise(fd, 0, count, advice);
372 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
377 ASSERTF(advice[0].lla_lockahead_result >= 0,
378 "unexpected extent result for extent %d: %d",
379 i, advice[0].lla_lockahead_result);
381 expected_lock_count++;
384 /* Ask again until we get the lock. */
385 for (i = 1; i < 100; i++) {
386 usleep(100000); /* 0.1 second */
387 advice[0].lla_lockahead_result = 456789;
388 rc = llapi_ladvise(fd, 0, count, advice);
389 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
390 mainpath, strerror(errno));
392 if (advice[0].lla_lockahead_result > 0)
396 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
397 "unexpected extent result: %d",
398 advice[0].lla_lockahead_result);
402 memset(buf, 0xaa, write_size);
403 rc = write(fd, buf, write_size);
404 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
405 mainpath, strerror(errno));
409 return expected_lock_count;
412 /* Request many locks at 10MiB intervals */
413 static int test15(void)
415 struct llapi_lu_ladvise *advice;
418 size_t write_size = 1024 * 1024;
420 char buf[write_size];
422 int expected_lock_count = 0;
424 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
425 ASSERTF(fd >= 0, "open failed for '%s': %s",
426 mainpath, strerror(errno));
428 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
430 for (i = 0; i < 5000; i++) {
431 /* The 'UL' designators are required to avoid undefined
432 * behavior which GCC turns in to an infinite loop */
433 __u64 start = i * 1024UL * 1024UL * 10UL;
434 __u64 end = start + 1;
436 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
439 advice[0].lla_lockahead_result = 345678;
441 rc = llapi_ladvise(fd, 0, count, advice);
443 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
444 mainpath, strerror(errno));
445 ASSERTF(advice[0].lla_lockahead_result >= 0,
446 "unexpected extent result for extent %d: %d",
447 i, advice[0].lla_lockahead_result);
448 expected_lock_count++;
451 /* Ask again until we get the lock. */
452 for (i = 1; i < 100; i++) {
453 usleep(100000); /* 0.1 second */
454 advice[0].lla_lockahead_result = 456789;
455 rc = llapi_ladvise(fd, 0, count, advice);
456 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
457 mainpath, strerror(errno));
459 if (advice[0].lla_lockahead_result > 0)
463 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
464 "unexpected extent result: %d",
465 advice[0].lla_lockahead_result);
467 memset(buf, 0xaa, write_size);
468 rc = write(fd, buf, write_size);
469 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
470 mainpath, strerror(errno));
471 /* The write should cancel the first lock (which was too small)
472 * and create one of its own, so the net effect on lock count is 0. */
478 /* We have to map our expected return in to the range of valid return
480 expected_lock_count = expected_lock_count/1000;
482 return expected_lock_count;
485 /* Use lockahead to verify behavior of ladvise locknoexpand */
486 static int test16(void)
488 struct llapi_lu_ladvise *advice;
489 struct llapi_lu_ladvise *advice_noexpand;
492 size_t write_size = 1024 * 1024;
494 __u64 end = write_size - 1;
496 char buf[write_size];
497 int expected_lock_count = 0;
499 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
500 ASSERTF(fd >= 0, "open failed for '%s': %s",
501 mainpath, strerror(errno));
503 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
504 advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
506 /* First ask for a read lock, which will conflict with the write */
507 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, false);
508 advice[0].lla_lockahead_result = 345678;
509 rc = llapi_ladvise(fd, 0, count, advice);
510 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
511 mainpath, strerror(errno));
512 ASSERTF(advice[0].lla_lockahead_result == 0,
513 "unexpected extent result for extent: %d",
514 advice[0].lla_lockahead_result);
516 /* Use an async request to verify we got the read lock we asked for */
517 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, true);
518 advice[0].lla_lockahead_result = 345678;
519 rc = llapi_ladvise(fd, 0, count, advice);
520 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
521 mainpath, strerror(errno));
522 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
523 "unexpected extent result for extent: %d",
524 advice[0].lla_lockahead_result);
527 advice_noexpand[0].lla_advice = LU_LADVISE_LOCKNOEXPAND;
528 advice_noexpand[0].lla_peradvice_flags = 0;
529 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
531 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
532 mainpath, strerror(errno));
534 /* This write should generate a lock on exactly "write_size" bytes */
535 memset(buf, 0xaa, write_size);
536 rc = write(fd, buf, write_size);
537 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
538 mainpath, strerror(errno));
539 /* Write should create one LDLM lock */
540 expected_lock_count++;
542 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
544 advice[0].lla_lockahead_result = 345678;
546 rc = llapi_ladvise(fd, 0, count, advice);
548 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
549 mainpath, strerror(errno));
550 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
551 "unexpected extent result for extent: %d",
552 advice[0].lla_lockahead_result);
554 /* Now, disable locknoexpand and try writing again. */
555 advice_noexpand[0].lla_peradvice_flags = LF_UNSET;
556 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
558 /* This write should get an expanded lock */
559 memset(buf, 0xaa, write_size);
560 rc = write(fd, buf, write_size);
561 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
562 mainpath, strerror(errno));
563 /* Write should create one LDLM lock */
564 expected_lock_count++;
566 /* Verify it didn't get a lock on just the bytes it wrote.*/
567 usleep(100000); /* 0.1 second, plenty of time to get the lock */
569 start = start + write_size;
570 end = end + write_size;
571 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
573 advice[0].lla_lockahead_result = 345678;
575 rc = llapi_ladvise(fd, 0, count, advice);
577 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
578 mainpath, strerror(errno));
579 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
580 "unexpected extent result for extent %d",
581 advice[0].lla_lockahead_result);
587 return expected_lock_count;
590 /* Use lockahead to verify behavior of ladvise locknoexpand, with O_NONBLOCK.
591 * There should be no change in behavior. */
592 static int test17(void)
594 struct llapi_lu_ladvise *advice;
595 struct llapi_lu_ladvise *advice_noexpand;
598 size_t write_size = 1024 * 1024;
600 __u64 end = write_size - 1;
602 char buf[write_size];
603 int expected_lock_count = 0;
605 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC | O_NONBLOCK,
607 ASSERTF(fd >= 0, "open failed for '%s': %s",
608 mainpath, strerror(errno));
610 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
611 advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
613 /* First ask for a read lock, which will conflict with the write */
614 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, false);
615 advice[0].lla_lockahead_result = 345678;
616 rc = llapi_ladvise(fd, 0, count, advice);
617 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
618 mainpath, strerror(errno));
619 ASSERTF(advice[0].lla_lockahead_result == 0,
620 "unexpected extent result for extent: %d",
621 advice[0].lla_lockahead_result);
623 /* Use an async request to verify we got the read lock we asked for */
624 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, true);
625 advice[0].lla_lockahead_result = 345678;
626 rc = llapi_ladvise(fd, 0, count, advice);
627 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
628 mainpath, strerror(errno));
629 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
630 "unexpected extent result for extent: %d",
631 advice[0].lla_lockahead_result);
634 advice_noexpand[0].lla_advice = LU_LADVISE_LOCKNOEXPAND;
635 advice_noexpand[0].lla_peradvice_flags = 0;
636 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
638 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
639 mainpath, strerror(errno));
641 /* This write should generate a lock on exactly "write_size" bytes */
642 memset(buf, 0xaa, write_size);
643 rc = write(fd, buf, write_size);
644 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
645 mainpath, strerror(errno));
646 /* Write should create one LDLM lock */
647 expected_lock_count++;
649 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
651 advice[0].lla_lockahead_result = 345678;
653 rc = llapi_ladvise(fd, 0, count, advice);
655 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
656 mainpath, strerror(errno));
657 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
658 "unexpected extent result for extent: %d",
659 advice[0].lla_lockahead_result);
661 /* Now, disable locknoexpand and try writing again. */
662 advice_noexpand[0].lla_peradvice_flags = LF_UNSET;
663 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
665 /* This write should get an expanded lock */
666 memset(buf, 0xaa, write_size);
667 rc = write(fd, buf, write_size);
668 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
669 mainpath, strerror(errno));
670 /* Write should create one LDLM lock */
671 expected_lock_count++;
673 /* Verify it didn't get a lock on just the bytes it wrote.*/
674 usleep(100000); /* 0.1 second, plenty of time to get the lock */
676 start = start + write_size;
677 end = end + write_size;
678 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
680 advice[0].lla_lockahead_result = 345678;
682 rc = llapi_ladvise(fd, 0, count, advice);
684 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
685 mainpath, strerror(errno));
686 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
687 "unexpected extent result for extent %d",
688 advice[0].lla_lockahead_result);
694 return expected_lock_count;
697 /* Test overlapping requests */
698 static int test18(void)
700 struct llapi_lu_ladvise *advice;
705 int expected_lock_count = 0;
707 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
708 ASSERTF(fd >= 0, "open failed for '%s': %s",
709 mainpath, strerror(errno));
711 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
713 /* Overlapping locks - Should only end up with 1 */
714 for (i = 0; i < 10; i++) {
716 __u64 end = start + 4096;
718 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
721 advice[0].lla_lockahead_result = 345678;
723 rc = llapi_ladvise(fd, 0, count, advice);
725 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
726 mainpath, strerror(errno));
727 ASSERTF(advice[0].lla_lockahead_result >= 0,
728 "unexpected extent result for extent %d: %d",
729 i, advice[0].lla_lockahead_result);
731 expected_lock_count = 1;
733 /* Ask again until we get the lock. */
734 for (i = 1; i < 100; i++) {
735 usleep(100000); /* 0.1 second */
736 advice[0].lla_lockahead_result = 456789;
737 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, 0, 4096,
739 rc = llapi_ladvise(fd, 0, count, advice);
740 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
741 mainpath, strerror(errno));
743 if (advice[0].lla_lockahead_result > 0)
747 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
748 "unexpected extent result: %d",
749 advice[0].lla_lockahead_result);
755 return expected_lock_count;
758 /* Test that normal request blocks lock ahead requests */
759 static int test19(void)
761 struct llapi_lu_ladvise *advice;
764 size_t write_size = 1024 * 1024;
766 char buf[write_size];
768 int expected_lock_count = 0;
770 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
771 ASSERTF(fd >= 0, "open failed for '%s': %s",
772 mainpath, strerror(errno));
774 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
776 /* This should create a lock on the whole file, which will block lock
778 memset(buf, 0xaa, write_size);
779 rc = write(fd, buf, write_size);
780 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
781 mainpath, strerror(errno));
783 expected_lock_count = 1;
785 /* These should all be blocked. */
786 for (i = 0; i < 10; i++) {
787 __u64 start = i * 4096;
788 __u64 end = start + 4096;
790 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
793 advice[0].lla_lockahead_result = 345678;
795 rc = llapi_ladvise(fd, 0, count, advice);
797 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
798 mainpath, strerror(errno));
799 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
800 "unexpected extent result for extent %d: %d",
801 i, advice[0].lla_lockahead_result);
808 return expected_lock_count;
811 /* Test sync requests, and matching with async requests */
812 static int test20(void)
814 struct llapi_lu_ladvise advice;
817 size_t write_size = 1024 * 1024;
819 char buf[write_size];
821 int expected_lock_count = 1;
823 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
824 ASSERTF(fd >= 0, "open failed for '%s': %s",
825 mainpath, strerror(errno));
828 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
829 write_size - 1, true);
831 /* Manually set the result so we can verify it's being modified */
832 advice.lla_lockahead_result = 345678;
834 rc = llapi_ladvise(fd, 0, count, &advice);
836 "cannot lockahead '%s': %s", mainpath, strerror(errno));
837 ASSERTF(advice.lla_lockahead_result == 0,
838 "unexpected extent result: %d",
839 advice.lla_lockahead_result);
841 /* Ask again until we get the lock (status 1). */
842 for (i = 1; i < 100; i++) {
843 usleep(100000); /* 0.1 second */
844 advice.lla_lockahead_result = 456789;
845 rc = llapi_ladvise(fd, 0, count, &advice);
846 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
847 mainpath, strerror(errno));
849 if (advice.lla_lockahead_result > 0)
853 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
854 "unexpected extent result: %d",
855 advice.lla_lockahead_result);
857 /* Convert to a sync request on smaller range, should match and not
859 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
860 write_size - 1 - write_size/2, false);
862 advice.lla_lockahead_result = 456789;
863 rc = llapi_ladvise(fd, 0, count, &advice);
864 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
865 mainpath, strerror(errno));
866 /* Sync requests cannot give detailed results */
867 ASSERTF(advice.lla_lockahead_result == 0,
868 "unexpected extent result: %d",
869 advice.lla_lockahead_result);
871 /* Use an async request to test original lock is still present */
872 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
873 write_size - 1, true);
875 advice.lla_lockahead_result = 456789;
876 rc = llapi_ladvise(fd, 0, count, &advice);
877 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
878 mainpath, strerror(errno));
879 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
880 "unexpected extent result: %d",
881 advice.lla_lockahead_result);
883 memset(buf, 0xaa, write_size);
884 rc = write(fd, buf, write_size);
885 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
886 mainpath, strerror(errno));
890 return expected_lock_count;
893 /* Test sync requests, and conflict with async requests */
894 static int test21(void)
896 struct llapi_lu_ladvise advice;
899 size_t write_size = 1024 * 1024;
901 char buf[write_size];
903 int expected_lock_count = 1;
905 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
906 ASSERTF(fd >= 0, "open failed for '%s': %s",
907 mainpath, strerror(errno));
910 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
911 write_size - 1, true);
913 /* Manually set the result so we can verify it's being modified */
914 advice.lla_lockahead_result = 345678;
916 rc = llapi_ladvise(fd, 0, count, &advice);
918 "cannot lockahead '%s': %s", mainpath, strerror(errno));
919 ASSERTF(advice.lla_lockahead_result == 0,
920 "unexpected extent result: %d",
921 advice.lla_lockahead_result);
923 /* Ask again until we get the lock (status 1). */
924 for (i = 1; i < 100; i++) {
925 usleep(100000); /* 0.1 second */
926 advice.lla_lockahead_result = 456789;
927 rc = llapi_ladvise(fd, 0, count, &advice);
928 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
929 mainpath, strerror(errno));
931 if (advice.lla_lockahead_result > 0)
935 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
936 "unexpected extent result: %d",
937 advice.lla_lockahead_result);
939 /* Convert to a sync request on larger range, should cancel existing
941 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
942 write_size*2 - 1, false);
944 advice.lla_lockahead_result = 456789;
945 rc = llapi_ladvise(fd, 0, count, &advice);
946 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
947 mainpath, strerror(errno));
948 /* Sync requests cannot give detailed results */
949 ASSERTF(advice.lla_lockahead_result == 0,
950 "unexpected extent result: %d",
951 advice.lla_lockahead_result);
953 /* Use an async request to test new lock is there */
954 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
955 write_size*2 - 1, true);
957 advice.lla_lockahead_result = 456789;
958 rc = llapi_ladvise(fd, 0, count, &advice);
959 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
960 mainpath, strerror(errno));
961 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
962 "unexpected extent result: %d",
963 advice.lla_lockahead_result);
965 memset(buf, 0xaa, write_size);
966 rc = write(fd, buf, write_size);
967 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
968 mainpath, strerror(errno));
972 return expected_lock_count;
975 /* Test various valid and invalid inputs */
976 static int test22(void)
978 struct llapi_lu_ladvise *advice;
985 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
986 ASSERTF(fd >= 0, "open failed for '%s': %s",
987 mainpath, strerror(errno));
989 /* A valid async request first */
990 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
993 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
994 rc = llapi_ladvise(fd, 0, count, advice);
995 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
996 mainpath, strerror(errno));
999 /* Valid request sync request */
1000 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1003 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, false);
1004 rc = llapi_ladvise(fd, 0, count, advice);
1005 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
1006 mainpath, strerror(errno));
1009 /* No actual block */
1010 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1013 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
1014 rc = llapi_ladvise(fd, 0, count, advice);
1015 ASSERTF(rc == -1 && errno == EINVAL,
1016 "unexpected return for no block lock: %d %s",
1017 rc, strerror(errno));
1020 /* end before start */
1021 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1022 start = 1024 * 1024;
1024 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
1025 rc = llapi_ladvise(fd, 0, count, advice);
1026 ASSERTF(rc == -1 && errno == EINVAL,
1027 "unexpected return for reversed block: %d %s",
1028 rc, strerror(errno));
1031 /* bogus lock mode - 0x65464 */
1032 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1035 setup_ladvise_lockahead(advice, 0x65464, 0, start, end, true);
1036 rc = llapi_ladvise(fd, 0, count, advice);
1037 ASSERTF(rc == -1 && errno == EINVAL,
1038 "unexpected return for bogus lock mode: %d %s",
1039 rc, strerror(errno));
1042 /* bogus flags, 0x80 */
1043 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1046 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0x80, start, end,
1048 rc = llapi_ladvise(fd, 0, count, advice);
1049 ASSERTF(rc == -1 && errno == EINVAL,
1050 "unexpected return for bogus flags: %u %d %s",
1051 0x80, rc, strerror(errno));
1054 /* bogus flags, 0xff - CEF_MASK */
1055 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1057 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xff, start, end,
1059 rc = llapi_ladvise(fd, 0, count, advice);
1060 ASSERTF(rc == -1 && errno == EINVAL,
1061 "unexpected return for bogus flags: %u %d %s",
1062 0xff, rc, strerror(errno));
1065 /* bogus flags, 0xffffffff */
1066 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1068 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xffffffff, start,
1070 rc = llapi_ladvise(fd, 0, count, advice);
1071 ASSERTF(rc == -1 && errno == EINVAL,
1072 "unexpected return for bogus flags: %u %d %s",
1073 0xffffffff, rc, strerror(errno));
1081 static void usage(char *prog)
1083 fprintf(stderr, "Usage: %s [-d lustre_dir], [-t single_test]\n", prog);
1087 static void process_args(int argc, char *argv[])
1091 while ((c = getopt(argc, argv, "d:t:")) != -1) {
1094 lustre_dir = optarg;
1097 single_test = atoi(optarg);
1101 fprintf(stderr, "Invalid option '%c'\n", optopt);
1108 int main(int argc, char *argv[])
1113 process_args(argc, argv);
1114 if (lustre_dir == NULL)
1115 lustre_dir = "/mnt/lustre";
1117 rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname);
1119 fprintf(stderr, "Error: '%s': not a Lustre filesystem\n",
1124 /* Play nice with Lustre test scripts. Non-line buffered output
1125 * stream under I/O redirection may appear incorrectly. */
1126 setvbuf(stdout, NULL, _IOLBF, 0);
1128 /* Create a test filename and reuse it. Remove possibly old files. */
1129 rc = snprintf(mainpath, sizeof(mainpath), "%s/%s", lustre_dir,
1131 ASSERTF(rc > 0 && rc < sizeof(mainpath), "invalid name for mainpath");
1136 switch (single_test) {
1151 /* When running all the test cases, we can't use the return
1152 * from the last test case, as it might be non-zero to return
1153 * info, rather than for an error. Test cases assert and exit
1154 * if an error occurs. */
1197 fprintf(stderr, "impossible value of single_test %d\n",