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 static char *mainfile;
79 static char fsmountdir[PATH_MAX]; /* Lustre mountpoint */
80 static char *lustre_dir; /* Test directory inside Lustre */
81 static int single_test; /* Number of a single test to execute*/
83 /* Cleanup our test file. */
84 static void cleanup(void)
89 /* Trivial helper for one advice */
90 void setup_ladvise_lockahead(struct llapi_lu_ladvise *advice, int mode,
91 int flags, size_t start, size_t end, bool async)
93 advice->lla_advice = LU_LADVISE_LOCKAHEAD;
94 advice->lla_lockahead_mode = mode;
96 advice->lla_peradvice_flags = flags | LF_ASYNC;
98 advice->lla_peradvice_flags = flags;
99 advice->lla_start = start;
100 advice->lla_end = end;
101 advice->lla_value3 = 0;
102 advice->lla_value4 = 0;
105 /* Test valid single lock ahead request */
106 static int test10(void)
108 struct llapi_lu_ladvise advice;
111 size_t write_size = 1024 * 1024;
113 char buf[write_size];
115 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
116 ASSERTF(fd >= 0, "open failed for '%s': %s",
117 mainpath, strerror(errno));
119 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
120 write_size - 1, true);
122 /* Manually set the result so we can verify it's being modified */
123 advice.lla_lockahead_result = 345678;
125 rc = llapi_ladvise(fd, 0, count, &advice);
127 "cannot lockahead '%s': %s", mainpath, strerror(errno));
128 ASSERTF(advice.lla_lockahead_result == 0,
129 "unexpected extent result: %d",
130 advice.lla_lockahead_result);
132 memset(buf, 0xaa, write_size);
133 rc = write(fd, buf, write_size);
134 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
135 mainpath, strerror(errno));
143 /* Get lock, wait until lock is taken */
144 static int test11(void)
146 struct llapi_lu_ladvise advice;
149 size_t write_size = 1024 * 1024;
151 char buf[write_size];
153 int enqueue_requests = 0;
155 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
156 ASSERTF(fd >= 0, "open failed for '%s': %s",
157 mainpath, strerror(errno));
159 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
160 write_size - 1, true);
162 /* Manually set the result so we can verify it's being modified */
163 advice.lla_lockahead_result = 345678;
165 rc = llapi_ladvise(fd, 0, count, &advice);
167 "cannot lockahead '%s': %s", mainpath, strerror(errno));
168 ASSERTF(advice.lla_lockahead_result == 0,
169 "unexpected extent result: %d",
170 advice.lla_lockahead_result);
174 /* Ask again until we get the lock (status 1). */
175 for (i = 1; i < 100; i++) {
176 usleep(100000); /* 0.1 second */
177 advice.lla_lockahead_result = 456789;
178 rc = llapi_ladvise(fd, 0, count, &advice);
179 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
180 mainpath, strerror(errno));
182 if (advice.lla_lockahead_result > 0)
188 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
189 "unexpected extent result: %d",
190 advice.lla_lockahead_result);
192 /* Again. This time it is always there. */
193 for (i = 0; i < 100; i++) {
194 advice.lla_lockahead_result = 456789;
195 rc = llapi_ladvise(fd, 0, count, &advice);
196 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
197 mainpath, strerror(errno));
198 ASSERTF(advice.lla_lockahead_result > 0,
199 "unexpected extent result: %d",
200 advice.lla_lockahead_result);
203 memset(buf, 0xaa, write_size);
204 rc = write(fd, buf, write_size);
205 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
206 mainpath, strerror(errno));
210 return enqueue_requests;
213 /* Test with several times the same extent */
214 static int test12(void)
216 struct llapi_lu_ladvise *advice;
217 const int count = 10;
219 size_t write_size = 1024 * 1024;
221 char buf[write_size];
223 int expected_lock_count = 0;
225 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
226 ASSERTF(fd >= 0, "open failed for '%s': %s",
227 mainpath, strerror(errno));
229 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
231 for (i = 0; i < count; i++) {
232 setup_ladvise_lockahead(&(advice[i]), MODE_WRITE_USER, 0, 0,
233 write_size - 1, true);
234 advice[i].lla_lockahead_result = 98674;
237 rc = llapi_ladvise(fd, 0, count, advice);
239 "cannot lockahead '%s': %s", mainpath, strerror(errno));
240 for (i = 0; i < count; i++) {
241 ASSERTF(advice[i].lla_lockahead_result >= 0,
242 "unexpected extent result for extent %d: %d",
243 i, advice[i].lla_lockahead_result);
245 /* Since all the requests are for the same extent, we should only have
246 * one lock at the end. */
247 expected_lock_count = 1;
249 /* Ask again until we get the locks. */
250 for (i = 1; i < 100; i++) {
251 usleep(100000); /* 0.1 second */
252 advice[count-1].lla_lockahead_result = 456789;
253 rc = llapi_ladvise(fd, 0, count, advice);
254 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
255 mainpath, strerror(errno));
257 if (advice[count-1].lla_lockahead_result > 0)
261 ASSERTF(advice[count-1].lla_lockahead_result == LLA_RESULT_SAME,
262 "unexpected extent result: %d",
263 advice[count-1].lla_lockahead_result);
265 memset(buf, 0xaa, write_size);
266 rc = write(fd, buf, write_size);
267 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
268 mainpath, strerror(errno));
273 return expected_lock_count;
276 /* Grow a lock forward */
277 static int test13(void)
279 struct llapi_lu_ladvise *advice = NULL;
282 size_t write_size = 1024 * 1024;
284 char buf[write_size];
286 int expected_lock_count = 0;
288 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
289 ASSERTF(fd >= 0, "open failed for '%s': %s",
290 mainpath, strerror(errno));
292 for (i = 0; i < 100; i++) {
295 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
296 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0,
297 i * write_size, (i+1)*write_size - 1,
299 advice[0].lla_lockahead_result = 98674;
301 rc = llapi_ladvise(fd, 0, count, advice);
302 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
307 ASSERTF(advice[0].lla_lockahead_result >= 0,
308 "unexpected extent result for extent %d: %d",
309 i, advice[0].lla_lockahead_result);
311 expected_lock_count++;
314 /* Ask again until we get the lock. */
315 for (i = 1; i < 100; i++) {
316 usleep(100000); /* 0.1 second */
317 advice[0].lla_lockahead_result = 456789;
318 rc = llapi_ladvise(fd, 0, count, advice);
319 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
320 mainpath, strerror(errno));
322 if (advice[0].lla_lockahead_result > 0)
326 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
327 "unexpected extent result: %d",
328 advice[0].lla_lockahead_result);
332 memset(buf, 0xaa, write_size);
333 rc = write(fd, buf, write_size);
334 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
335 mainpath, strerror(errno));
339 return expected_lock_count;
342 /* Grow a lock backward */
343 static int test14(void)
345 struct llapi_lu_ladvise *advice = NULL;
348 size_t write_size = 1024 * 1024;
350 char buf[write_size];
352 const int num_blocks = 100;
353 int expected_lock_count = 0;
355 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
356 ASSERTF(fd >= 0, "open failed for '%s': %s",
357 mainpath, strerror(errno));
359 for (i = 0; i < num_blocks; i++) {
360 size_t start = (num_blocks - i - 1) * write_size;
361 size_t end = (num_blocks - i) * write_size - 1;
365 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
366 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
368 advice[0].lla_lockahead_result = 98674;
370 rc = llapi_ladvise(fd, 0, count, advice);
371 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
376 ASSERTF(advice[0].lla_lockahead_result >= 0,
377 "unexpected extent result for extent %d: %d",
378 i, advice[0].lla_lockahead_result);
380 expected_lock_count++;
383 /* Ask again until we get the lock. */
384 for (i = 1; i < 100; i++) {
385 usleep(100000); /* 0.1 second */
386 advice[0].lla_lockahead_result = 456789;
387 rc = llapi_ladvise(fd, 0, count, advice);
388 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
389 mainpath, strerror(errno));
391 if (advice[0].lla_lockahead_result > 0)
395 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
396 "unexpected extent result: %d",
397 advice[0].lla_lockahead_result);
401 memset(buf, 0xaa, write_size);
402 rc = write(fd, buf, write_size);
403 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
404 mainpath, strerror(errno));
408 return expected_lock_count;
411 /* Request many locks at 10MiB intervals */
412 static int test15(void)
414 struct llapi_lu_ladvise *advice;
417 size_t write_size = 1024 * 1024;
419 char buf[write_size];
421 int expected_lock_count = 0;
423 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
424 ASSERTF(fd >= 0, "open failed for '%s': %s",
425 mainpath, strerror(errno));
427 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
429 for (i = 0; i < 500; i++) {
430 /* The 'UL' designators are required to avoid undefined
431 * behavior which GCC turns in to an infinite loop */
432 __u64 start = i * 1024UL * 1024UL * 10UL;
433 __u64 end = start + 1;
435 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
438 advice[0].lla_lockahead_result = 345678;
440 rc = llapi_ladvise(fd, 0, count, advice);
442 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
443 mainpath, strerror(errno));
444 ASSERTF(advice[0].lla_lockahead_result >= 0,
445 "unexpected extent result for extent %d: %d",
446 i, advice[0].lla_lockahead_result);
447 expected_lock_count++;
450 /* Ask again until we get the lock. */
451 for (i = 1; i < 100; i++) {
452 usleep(100000); /* 0.1 second */
453 advice[0].lla_lockahead_result = 456789;
454 rc = llapi_ladvise(fd, 0, count, advice);
455 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
456 mainpath, strerror(errno));
458 if (advice[0].lla_lockahead_result > 0)
462 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
463 "unexpected extent result: %d",
464 advice[0].lla_lockahead_result);
466 memset(buf, 0xaa, write_size);
467 rc = write(fd, buf, write_size);
468 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
469 mainpath, strerror(errno));
470 /* The write should cancel the first lock (which was too small)
471 * and create one of its own, so the net effect on lock count is 0. */
477 /* We have to map our expected return in to the range of valid return
479 expected_lock_count = expected_lock_count/100;
481 return expected_lock_count;
484 /* Use lockahead to verify behavior of ladvise locknoexpand */
485 static int test16(void)
487 struct llapi_lu_ladvise *advice;
488 struct llapi_lu_ladvise *advice_noexpand;
491 size_t write_size = 1024 * 1024;
493 __u64 end = write_size - 1;
495 char buf[write_size];
496 int expected_lock_count = 0;
498 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
499 ASSERTF(fd >= 0, "open failed for '%s': %s",
500 mainpath, strerror(errno));
502 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
503 advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
505 /* First ask for a read lock, which will conflict with the write */
506 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, false);
507 advice[0].lla_lockahead_result = 345678;
508 rc = llapi_ladvise(fd, 0, count, advice);
509 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
510 mainpath, strerror(errno));
511 ASSERTF(advice[0].lla_lockahead_result == 0,
512 "unexpected extent result for extent: %d",
513 advice[0].lla_lockahead_result);
515 /* Use an async request to verify we got the read lock we asked for */
516 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, true);
517 advice[0].lla_lockahead_result = 345678;
518 rc = llapi_ladvise(fd, 0, count, advice);
519 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
520 mainpath, strerror(errno));
521 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
522 "unexpected extent result for extent: %d",
523 advice[0].lla_lockahead_result);
526 advice_noexpand[0].lla_advice = LU_LADVISE_LOCKNOEXPAND;
527 advice_noexpand[0].lla_peradvice_flags = 0;
528 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
530 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
531 mainpath, strerror(errno));
533 /* This write should generate a lock on exactly "write_size" bytes */
534 memset(buf, 0xaa, write_size);
535 rc = write(fd, buf, write_size);
536 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
537 mainpath, strerror(errno));
538 /* Write should create one LDLM lock */
539 expected_lock_count++;
541 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
543 advice[0].lla_lockahead_result = 345678;
545 rc = llapi_ladvise(fd, 0, count, advice);
547 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
548 mainpath, strerror(errno));
549 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
550 "unexpected extent result for extent: %d",
551 advice[0].lla_lockahead_result);
553 /* Now, disable locknoexpand and try writing again. */
554 advice_noexpand[0].lla_peradvice_flags = LF_UNSET;
555 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
557 /* This write should get an expanded lock */
558 memset(buf, 0xaa, write_size);
559 rc = write(fd, buf, write_size);
560 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
561 mainpath, strerror(errno));
562 /* Write should create one LDLM lock */
563 expected_lock_count++;
565 /* Verify it didn't get a lock on just the bytes it wrote.*/
566 usleep(100000); /* 0.1 second, plenty of time to get the lock */
568 start = start + write_size;
569 end = end + write_size;
570 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
572 advice[0].lla_lockahead_result = 345678;
574 rc = llapi_ladvise(fd, 0, count, advice);
576 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
577 mainpath, strerror(errno));
578 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
579 "unexpected extent result for extent %d",
580 advice[0].lla_lockahead_result);
586 return expected_lock_count;
589 /* Use lockahead to verify behavior of ladvise locknoexpand, with O_NONBLOCK.
590 * There should be no change in behavior. */
591 static int test17(void)
593 struct llapi_lu_ladvise *advice;
594 struct llapi_lu_ladvise *advice_noexpand;
597 size_t write_size = 1024 * 1024;
599 __u64 end = write_size - 1;
601 char buf[write_size];
602 int expected_lock_count = 0;
604 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC | O_NONBLOCK,
606 ASSERTF(fd >= 0, "open failed for '%s': %s",
607 mainpath, strerror(errno));
609 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
610 advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
612 /* First ask for a read lock, which will conflict with the write */
613 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, false);
614 advice[0].lla_lockahead_result = 345678;
615 rc = llapi_ladvise(fd, 0, count, advice);
616 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
617 mainpath, strerror(errno));
618 ASSERTF(advice[0].lla_lockahead_result == 0,
619 "unexpected extent result for extent: %d",
620 advice[0].lla_lockahead_result);
622 /* Use an async request to verify we got the read lock we asked for */
623 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, true);
624 advice[0].lla_lockahead_result = 345678;
625 rc = llapi_ladvise(fd, 0, count, advice);
626 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
627 mainpath, strerror(errno));
628 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
629 "unexpected extent result for extent: %d",
630 advice[0].lla_lockahead_result);
633 advice_noexpand[0].lla_advice = LU_LADVISE_LOCKNOEXPAND;
634 advice_noexpand[0].lla_peradvice_flags = 0;
635 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
637 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
638 mainpath, strerror(errno));
640 /* This write should generate a lock on exactly "write_size" bytes */
641 memset(buf, 0xaa, write_size);
642 rc = write(fd, buf, write_size);
643 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
644 mainpath, strerror(errno));
645 /* Write should create one LDLM lock */
646 expected_lock_count++;
648 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
650 advice[0].lla_lockahead_result = 345678;
652 rc = llapi_ladvise(fd, 0, count, advice);
654 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
655 mainpath, strerror(errno));
656 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
657 "unexpected extent result for extent: %d",
658 advice[0].lla_lockahead_result);
660 /* Now, disable locknoexpand and try writing again. */
661 advice_noexpand[0].lla_peradvice_flags = LF_UNSET;
662 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
664 /* This write should get an expanded lock */
665 memset(buf, 0xaa, write_size);
666 rc = write(fd, buf, write_size);
667 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
668 mainpath, strerror(errno));
669 /* Write should create one LDLM lock */
670 expected_lock_count++;
672 /* Verify it didn't get a lock on just the bytes it wrote.*/
673 usleep(100000); /* 0.1 second, plenty of time to get the lock */
675 start = start + write_size;
676 end = end + write_size;
677 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
679 advice[0].lla_lockahead_result = 345678;
681 rc = llapi_ladvise(fd, 0, count, advice);
683 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
684 mainpath, strerror(errno));
685 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
686 "unexpected extent result for extent %d",
687 advice[0].lla_lockahead_result);
693 return expected_lock_count;
696 /* Test overlapping requests */
697 static int test18(void)
699 struct llapi_lu_ladvise *advice;
704 int expected_lock_count = 0;
706 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
707 ASSERTF(fd >= 0, "open failed for '%s': %s",
708 mainpath, strerror(errno));
710 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
712 /* Overlapping locks - Should only end up with 1 */
713 for (i = 0; i < 10; i++) {
715 __u64 end = start + 4096;
717 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
720 advice[0].lla_lockahead_result = 345678;
722 rc = llapi_ladvise(fd, 0, count, advice);
724 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
725 mainpath, strerror(errno));
726 ASSERTF(advice[0].lla_lockahead_result >= 0,
727 "unexpected extent result for extent %d: %d",
728 i, advice[0].lla_lockahead_result);
730 expected_lock_count = 1;
732 /* Ask again until we get the lock. */
733 for (i = 1; i < 100; i++) {
734 usleep(100000); /* 0.1 second */
735 advice[0].lla_lockahead_result = 456789;
736 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, 0, 4096,
738 rc = llapi_ladvise(fd, 0, count, advice);
739 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
740 mainpath, strerror(errno));
742 if (advice[0].lla_lockahead_result > 0)
746 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
747 "unexpected extent result: %d",
748 advice[0].lla_lockahead_result);
754 return expected_lock_count;
757 /* Test that normal request blocks lock ahead requests */
758 static int test19(void)
760 struct llapi_lu_ladvise *advice;
763 size_t write_size = 1024 * 1024;
765 char buf[write_size];
767 int expected_lock_count = 0;
769 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
770 ASSERTF(fd >= 0, "open failed for '%s': %s",
771 mainpath, strerror(errno));
773 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
775 /* This should create a lock on the whole file, which will block lock
777 memset(buf, 0xaa, write_size);
778 rc = write(fd, buf, write_size);
779 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
780 mainpath, strerror(errno));
782 expected_lock_count = 1;
784 /* These should all be blocked. */
785 for (i = 0; i < 10; i++) {
786 __u64 start = i * 4096;
787 __u64 end = start + 4096;
789 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
792 advice[0].lla_lockahead_result = 345678;
794 rc = llapi_ladvise(fd, 0, count, advice);
796 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
797 mainpath, strerror(errno));
798 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
799 "unexpected extent result for extent %d: %d",
800 i, advice[0].lla_lockahead_result);
807 return expected_lock_count;
810 /* Test sync requests, and matching with async requests */
811 static int test20(void)
813 struct llapi_lu_ladvise advice;
816 size_t write_size = 1024 * 1024;
818 char buf[write_size];
820 int expected_lock_count = 1;
822 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
823 ASSERTF(fd >= 0, "open failed for '%s': %s",
824 mainpath, strerror(errno));
827 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
828 write_size - 1, true);
830 /* Manually set the result so we can verify it's being modified */
831 advice.lla_lockahead_result = 345678;
833 rc = llapi_ladvise(fd, 0, count, &advice);
835 "cannot lockahead '%s': %s", mainpath, strerror(errno));
836 ASSERTF(advice.lla_lockahead_result == 0,
837 "unexpected extent result: %d",
838 advice.lla_lockahead_result);
840 /* Ask again until we get the lock (status 1). */
841 for (i = 1; i < 100; i++) {
842 usleep(100000); /* 0.1 second */
843 advice.lla_lockahead_result = 456789;
844 rc = llapi_ladvise(fd, 0, count, &advice);
845 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
846 mainpath, strerror(errno));
848 if (advice.lla_lockahead_result > 0)
852 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
853 "unexpected extent result: %d",
854 advice.lla_lockahead_result);
856 /* Convert to a sync request on smaller range, should match and not
858 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
859 write_size - 1 - write_size/2, false);
861 advice.lla_lockahead_result = 456789;
862 rc = llapi_ladvise(fd, 0, count, &advice);
863 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
864 mainpath, strerror(errno));
865 /* Sync requests cannot give detailed results */
866 ASSERTF(advice.lla_lockahead_result == 0,
867 "unexpected extent result: %d",
868 advice.lla_lockahead_result);
870 /* Use an async request to test original lock is still present */
871 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
872 write_size - 1, true);
874 advice.lla_lockahead_result = 456789;
875 rc = llapi_ladvise(fd, 0, count, &advice);
876 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
877 mainpath, strerror(errno));
878 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
879 "unexpected extent result: %d",
880 advice.lla_lockahead_result);
882 memset(buf, 0xaa, write_size);
883 rc = write(fd, buf, write_size);
884 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
885 mainpath, strerror(errno));
889 return expected_lock_count;
892 /* Test sync requests, and conflict with async requests */
893 static int test21(void)
895 struct llapi_lu_ladvise advice;
898 size_t write_size = 1024 * 1024;
900 char buf[write_size];
902 int expected_lock_count = 1;
904 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
905 ASSERTF(fd >= 0, "open failed for '%s': %s",
906 mainpath, strerror(errno));
909 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
910 write_size - 1, true);
912 /* Manually set the result so we can verify it's being modified */
913 advice.lla_lockahead_result = 345678;
915 rc = llapi_ladvise(fd, 0, count, &advice);
917 "cannot lockahead '%s': %s", mainpath, strerror(errno));
918 ASSERTF(advice.lla_lockahead_result == 0,
919 "unexpected extent result: %d",
920 advice.lla_lockahead_result);
922 /* Ask again until we get the lock (status 1). */
923 for (i = 1; i < 100; i++) {
924 usleep(100000); /* 0.1 second */
925 advice.lla_lockahead_result = 456789;
926 rc = llapi_ladvise(fd, 0, count, &advice);
927 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
928 mainpath, strerror(errno));
930 if (advice.lla_lockahead_result > 0)
934 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
935 "unexpected extent result: %d",
936 advice.lla_lockahead_result);
938 /* Convert to a sync request on larger range, should cancel existing
940 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
941 write_size*2 - 1, false);
943 advice.lla_lockahead_result = 456789;
944 rc = llapi_ladvise(fd, 0, count, &advice);
945 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
946 mainpath, strerror(errno));
947 /* Sync requests cannot give detailed results */
948 ASSERTF(advice.lla_lockahead_result == 0,
949 "unexpected extent result: %d",
950 advice.lla_lockahead_result);
952 /* Use an async request to test new lock is there */
953 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
954 write_size*2 - 1, true);
956 advice.lla_lockahead_result = 456789;
957 rc = llapi_ladvise(fd, 0, count, &advice);
958 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
959 mainpath, strerror(errno));
960 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
961 "unexpected extent result: %d",
962 advice.lla_lockahead_result);
964 memset(buf, 0xaa, write_size);
965 rc = write(fd, buf, write_size);
966 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
967 mainpath, strerror(errno));
971 return expected_lock_count;
974 /* Test various valid and invalid inputs */
975 static int test22(void)
977 struct llapi_lu_ladvise *advice;
984 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
985 ASSERTF(fd >= 0, "open failed for '%s': %s",
986 mainpath, strerror(errno));
988 /* A valid async request first */
989 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
992 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
993 rc = llapi_ladvise(fd, 0, count, advice);
994 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
995 mainpath, strerror(errno));
998 /* Valid request sync request */
999 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1002 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, false);
1003 rc = llapi_ladvise(fd, 0, count, advice);
1004 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
1005 mainpath, strerror(errno));
1008 /* No actual block */
1009 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1012 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
1013 rc = llapi_ladvise(fd, 0, count, advice);
1014 ASSERTF(rc == -1 && errno == EINVAL,
1015 "unexpected return for no block lock: %d %s",
1016 rc, strerror(errno));
1019 /* end before start */
1020 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1021 start = 1024 * 1024;
1023 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
1024 rc = llapi_ladvise(fd, 0, count, advice);
1025 ASSERTF(rc == -1 && errno == EINVAL,
1026 "unexpected return for reversed block: %d %s",
1027 rc, strerror(errno));
1030 /* bogus lock mode - 0x65464 */
1031 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1034 setup_ladvise_lockahead(advice, 0x65464, 0, start, end, true);
1035 rc = llapi_ladvise(fd, 0, count, advice);
1036 ASSERTF(rc == -1 && errno == EINVAL,
1037 "unexpected return for bogus lock mode: %d %s",
1038 rc, strerror(errno));
1041 /* bogus flags, 0x80 */
1042 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1045 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0x80, start, end,
1047 rc = llapi_ladvise(fd, 0, count, advice);
1048 ASSERTF(rc == -1 && errno == EINVAL,
1049 "unexpected return for bogus flags: %u %d %s",
1050 0x80, rc, strerror(errno));
1053 /* bogus flags, 0xff - CEF_MASK */
1054 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1056 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xff, start, end,
1058 rc = llapi_ladvise(fd, 0, count, advice);
1059 ASSERTF(rc == -1 && errno == EINVAL,
1060 "unexpected return for bogus flags: %u %d %s",
1061 0xff, rc, strerror(errno));
1064 /* bogus flags, 0xffffffff */
1065 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1067 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xffffffff, start,
1069 rc = llapi_ladvise(fd, 0, count, advice);
1070 ASSERTF(rc == -1 && errno == EINVAL,
1071 "unexpected return for bogus flags: %u %d %s",
1072 0xffffffff, rc, strerror(errno));
1080 static void usage(char *prog)
1082 fprintf(stderr, "Usage: %s [-d lustre_dir], [-t single_test]\n", prog);
1086 static void process_args(int argc, char *argv[])
1090 while ((c = getopt(argc, argv, "d:f:t:")) != -1) {
1096 lustre_dir = optarg;
1099 single_test = atoi(optarg);
1103 fprintf(stderr, "Invalid option '%c'\n", optopt);
1110 int main(int argc, char *argv[])
1115 process_args(argc, argv);
1116 if (lustre_dir == NULL)
1117 lustre_dir = "/mnt/lustre";
1118 if (mainfile == NULL)
1119 mainfile = "lockahead_test_654";
1121 rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname);
1123 fprintf(stderr, "Error: '%s': not a Lustre filesystem\n",
1128 /* Play nice with Lustre test scripts. Non-line buffered output
1129 * stream under I/O redirection may appear incorrectly. */
1130 setvbuf(stdout, NULL, _IOLBF, 0);
1132 /* Create a test filename and reuse it. Remove possibly old files. */
1133 rc = snprintf(mainpath, sizeof(mainpath), "%s/%s", lustre_dir,
1135 ASSERTF(rc > 0 && rc < sizeof(mainpath), "invalid name for mainpath");
1138 switch (single_test) {
1153 /* When running all the test cases, we can't use the return
1154 * from the last test case, as it might be non-zero to return
1155 * info, rather than for an error. Test cases assert and exit
1156 * if an error occurs. */
1199 fprintf(stderr, "impossible value of single_test %d\n",