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 static 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, 0600);
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, 0600);
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, 0600);
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.
251 expected_lock_count = 1;
253 /* Ask again until we get the locks. */
254 for (i = 1; i < 100; i++) {
255 usleep(100000); /* 0.1 second */
256 advice[count-1].lla_lockahead_result = 456789;
257 rc = llapi_ladvise(fd, 0, count, advice);
258 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
259 mainpath, strerror(errno));
261 if (advice[count-1].lla_lockahead_result > 0)
265 ASSERTF(advice[count-1].lla_lockahead_result == LLA_RESULT_SAME,
266 "unexpected extent result: %d",
267 advice[count-1].lla_lockahead_result);
269 memset(buf, 0xaa, write_size);
270 rc = write(fd, buf, write_size);
271 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
272 mainpath, strerror(errno));
277 return expected_lock_count;
280 /* Grow a lock forward */
281 static int test13(void)
283 struct llapi_lu_ladvise *advice = NULL;
286 size_t write_size = 1024 * 1024;
288 char buf[write_size];
290 int expected_lock_count = 0;
292 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, 0600);
293 ASSERTF(fd >= 0, "open failed for '%s': %s",
294 mainpath, strerror(errno));
296 for (i = 0; i < 100; i++) {
299 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
300 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0,
301 i * write_size, (i+1)*write_size - 1,
303 advice[0].lla_lockahead_result = 98674;
305 rc = llapi_ladvise(fd, 0, count, advice);
306 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
311 ASSERTF(advice[0].lla_lockahead_result >= 0,
312 "unexpected extent result for extent %d: %d",
313 i, advice[0].lla_lockahead_result);
315 expected_lock_count++;
318 /* Ask again until we get the lock. */
319 for (i = 1; i < 100; i++) {
320 usleep(100000); /* 0.1 second */
321 advice[0].lla_lockahead_result = 456789;
322 rc = llapi_ladvise(fd, 0, count, advice);
323 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
324 mainpath, strerror(errno));
326 if (advice[0].lla_lockahead_result > 0)
330 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
331 "unexpected extent result: %d",
332 advice[0].lla_lockahead_result);
336 memset(buf, 0xaa, write_size);
337 rc = write(fd, buf, write_size);
338 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
339 mainpath, strerror(errno));
343 return expected_lock_count;
346 /* Grow a lock backward */
347 static int test14(void)
349 struct llapi_lu_ladvise *advice = NULL;
352 size_t write_size = 1024 * 1024;
354 char buf[write_size];
356 const int num_blocks = 100;
357 int expected_lock_count = 0;
359 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, 0600);
360 ASSERTF(fd >= 0, "open failed for '%s': %s",
361 mainpath, strerror(errno));
363 for (i = 0; i < num_blocks; i++) {
364 size_t start = (num_blocks - i - 1) * write_size;
365 size_t end = (num_blocks - i) * write_size - 1;
369 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
370 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
372 advice[0].lla_lockahead_result = 98674;
374 rc = llapi_ladvise(fd, 0, count, advice);
375 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
380 ASSERTF(advice[0].lla_lockahead_result >= 0,
381 "unexpected extent result for extent %d: %d",
382 i, advice[0].lla_lockahead_result);
384 expected_lock_count++;
387 /* Ask again until we get the lock. */
388 for (i = 1; i < 100; i++) {
389 usleep(100000); /* 0.1 second */
390 advice[0].lla_lockahead_result = 456789;
391 rc = llapi_ladvise(fd, 0, count, advice);
392 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
393 mainpath, strerror(errno));
395 if (advice[0].lla_lockahead_result > 0)
399 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
400 "unexpected extent result: %d",
401 advice[0].lla_lockahead_result);
405 memset(buf, 0xaa, write_size);
406 rc = write(fd, buf, write_size);
407 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
408 mainpath, strerror(errno));
412 return expected_lock_count;
415 /* Request many locks at 10MiB intervals */
416 static int test15(void)
418 struct llapi_lu_ladvise *advice;
421 size_t write_size = 1024 * 1024;
423 char buf[write_size];
425 int expected_lock_count = 0;
427 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, 0600);
428 ASSERTF(fd >= 0, "open failed for '%s': %s",
429 mainpath, strerror(errno));
431 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
433 for (i = 0; i < 100; i++) {
434 /* The 'UL' designators are required to avoid undefined
435 * behavior which GCC turns in to an infinite loop
437 __u64 start = i * 1024UL * 1024UL * 10UL;
438 __u64 end = start + 1;
440 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
443 advice[0].lla_lockahead_result = 345678;
445 rc = llapi_ladvise(fd, 0, count, advice);
447 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
448 mainpath, strerror(errno));
449 ASSERTF(advice[0].lla_lockahead_result >= 0,
450 "unexpected extent result for extent %d: %d",
451 i, advice[0].lla_lockahead_result);
452 expected_lock_count++;
455 /* Ask again until we get the lock. */
456 for (i = 1; i < 100; i++) {
457 usleep(100000); /* 0.1 second */
458 advice[0].lla_lockahead_result = 456789;
459 rc = llapi_ladvise(fd, 0, count, advice);
460 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
461 mainpath, strerror(errno));
463 if (advice[0].lla_lockahead_result > 0)
467 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
468 "unexpected extent result: %d",
469 advice[0].lla_lockahead_result);
471 memset(buf, 0xaa, write_size);
472 rc = write(fd, buf, write_size);
473 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
474 mainpath, strerror(errno));
475 /* The write should cancel the first lock (which was too small)
476 * and create one of its own, so the net effect on lock count is 0.
483 /* have to map expected return to range of valid values, 0-255 */
484 expected_lock_count = expected_lock_count/100;
486 return expected_lock_count;
489 /* Use lockahead to verify behavior of ladvise locknoexpand */
490 static int test16(void)
492 struct llapi_lu_ladvise *advice;
493 struct llapi_lu_ladvise *advice_noexpand;
496 size_t write_size = 1024 * 1024;
498 __u64 end = write_size - 1;
500 char buf[write_size];
501 int expected_lock_count = 0;
503 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, 0600);
504 ASSERTF(fd >= 0, "open failed for '%s': %s",
505 mainpath, strerror(errno));
507 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
508 advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
510 /* First ask for a read lock, which will conflict with the write */
511 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, false);
512 advice[0].lla_lockahead_result = 345678;
513 rc = llapi_ladvise(fd, 0, count, advice);
514 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
515 mainpath, strerror(errno));
516 ASSERTF(advice[0].lla_lockahead_result == 0,
517 "unexpected extent result for extent: %d",
518 advice[0].lla_lockahead_result);
520 /* Use an async request to verify we got the read lock we asked for */
521 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, true);
522 advice[0].lla_lockahead_result = 345678;
523 rc = llapi_ladvise(fd, 0, count, advice);
524 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
525 mainpath, strerror(errno));
526 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
527 "unexpected extent result for extent: %d",
528 advice[0].lla_lockahead_result);
531 advice_noexpand[0].lla_advice = LU_LADVISE_LOCKNOEXPAND;
532 advice_noexpand[0].lla_peradvice_flags = 0;
533 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
535 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
536 mainpath, strerror(errno));
538 /* This write should generate a lock on exactly "write_size" bytes */
539 memset(buf, 0xaa, write_size);
540 rc = write(fd, buf, write_size);
541 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
542 mainpath, strerror(errno));
543 /* Write should create one LDLM lock */
544 expected_lock_count++;
546 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
548 advice[0].lla_lockahead_result = 345678;
550 rc = llapi_ladvise(fd, 0, count, advice);
552 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
553 mainpath, strerror(errno));
554 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
555 "unexpected extent result for extent: %d",
556 advice[0].lla_lockahead_result);
558 /* Now, disable locknoexpand and try writing again. */
559 advice_noexpand[0].lla_peradvice_flags = LF_UNSET;
560 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
562 /* This write should get an expanded lock */
563 memset(buf, 0xaa, write_size);
564 rc = write(fd, buf, write_size);
565 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
566 mainpath, strerror(errno));
567 /* Write should create one LDLM lock */
568 expected_lock_count++;
570 /* Verify it didn't get a lock on just the bytes it wrote.*/
571 usleep(100000); /* 0.1 second, plenty of time to get the lock */
573 start = start + write_size;
574 end = end + write_size;
575 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
577 advice[0].lla_lockahead_result = 345678;
579 rc = llapi_ladvise(fd, 0, count, advice);
581 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
582 mainpath, strerror(errno));
583 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
584 "unexpected extent result for extent %d",
585 advice[0].lla_lockahead_result);
591 return expected_lock_count;
594 /* Use lockahead to verify behavior of ladvise locknoexpand, with O_NONBLOCK.
595 * There should be no change in behavior.
597 static int test17(void)
599 struct llapi_lu_ladvise *advice;
600 struct llapi_lu_ladvise *advice_noexpand;
603 size_t write_size = 1024 * 1024;
605 __u64 end = write_size - 1;
607 char buf[write_size];
608 int expected_lock_count = 0;
610 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC | O_NONBLOCK, 0600);
611 ASSERTF(fd >= 0, "open failed for '%s': %s",
612 mainpath, strerror(errno));
614 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
615 advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
617 /* First ask for a read lock, which will conflict with the write */
618 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, false);
619 advice[0].lla_lockahead_result = 345678;
620 rc = llapi_ladvise(fd, 0, count, advice);
621 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
622 mainpath, strerror(errno));
623 ASSERTF(advice[0].lla_lockahead_result == 0,
624 "unexpected extent result for extent: %d",
625 advice[0].lla_lockahead_result);
627 /* Use an async request to verify we got the read lock we asked for */
628 setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, true);
629 advice[0].lla_lockahead_result = 345678;
630 rc = llapi_ladvise(fd, 0, count, advice);
631 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
632 mainpath, strerror(errno));
633 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
634 "unexpected extent result for extent: %d",
635 advice[0].lla_lockahead_result);
638 advice_noexpand[0].lla_advice = LU_LADVISE_LOCKNOEXPAND;
639 advice_noexpand[0].lla_peradvice_flags = 0;
640 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
642 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
643 mainpath, strerror(errno));
645 /* This write should generate a lock on exactly "write_size" bytes */
646 memset(buf, 0xaa, write_size);
647 rc = write(fd, buf, write_size);
648 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
649 mainpath, strerror(errno));
650 /* Write should create one LDLM lock */
651 expected_lock_count++;
653 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
655 advice[0].lla_lockahead_result = 345678;
657 rc = llapi_ladvise(fd, 0, count, advice);
659 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
660 mainpath, strerror(errno));
661 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
662 "unexpected extent result for extent: %d",
663 advice[0].lla_lockahead_result);
665 /* Now, disable locknoexpand and try writing again. */
666 advice_noexpand[0].lla_peradvice_flags = LF_UNSET;
667 rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
669 /* This write should get an expanded lock */
670 memset(buf, 0xaa, write_size);
671 rc = write(fd, buf, write_size);
672 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
673 mainpath, strerror(errno));
674 /* Write should create one LDLM lock */
675 expected_lock_count++;
677 /* Verify it didn't get a lock on just the bytes it wrote.*/
678 usleep(100000); /* 0.1 second, plenty of time to get the lock */
680 start = start + write_size;
681 end = end + write_size;
682 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
684 advice[0].lla_lockahead_result = 345678;
686 rc = llapi_ladvise(fd, 0, count, advice);
688 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
689 mainpath, strerror(errno));
690 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
691 "unexpected extent result for extent %d",
692 advice[0].lla_lockahead_result);
698 return expected_lock_count;
701 /* Test overlapping requests */
702 static int test18(void)
704 struct llapi_lu_ladvise *advice;
709 int expected_lock_count = 0;
711 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, 0600);
712 ASSERTF(fd >= 0, "open failed for '%s': %s",
713 mainpath, strerror(errno));
715 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
717 /* Overlapping locks - Should only end up with 1 */
718 for (i = 0; i < 10; i++) {
720 __u64 end = start + 4096;
722 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
725 advice[0].lla_lockahead_result = 345678;
727 rc = llapi_ladvise(fd, 0, count, advice);
729 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
730 mainpath, strerror(errno));
731 ASSERTF(advice[0].lla_lockahead_result >= 0,
732 "unexpected extent result for extent %d: %d",
733 i, advice[0].lla_lockahead_result);
735 expected_lock_count = 1;
737 /* Ask again until we get the lock. */
738 for (i = 1; i < 100; i++) {
739 usleep(100000); /* 0.1 second */
740 advice[0].lla_lockahead_result = 456789;
741 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, 0, 4096,
743 rc = llapi_ladvise(fd, 0, count, advice);
744 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
745 mainpath, strerror(errno));
747 if (advice[0].lla_lockahead_result > 0)
751 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
752 "unexpected extent result: %d",
753 advice[0].lla_lockahead_result);
759 return expected_lock_count;
762 /* Test that normal request blocks lock ahead requests */
763 static int test19(void)
765 struct llapi_lu_ladvise *advice;
768 size_t write_size = 1024 * 1024;
770 char buf[write_size];
772 int expected_lock_count = 0;
774 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, 0600);
775 ASSERTF(fd >= 0, "open failed for '%s': %s",
776 mainpath, strerror(errno));
778 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
780 /* This should create a lock on the whole file, which will block lock
783 memset(buf, 0xaa, write_size);
784 rc = write(fd, buf, write_size);
785 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
786 mainpath, strerror(errno));
788 expected_lock_count = 1;
790 /* These should all be blocked. */
791 for (i = 0; i < 10; i++) {
792 __u64 start = i * 4096;
793 __u64 end = start + 4096;
795 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
798 advice[0].lla_lockahead_result = 345678;
800 rc = llapi_ladvise(fd, 0, count, advice);
802 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
803 mainpath, strerror(errno));
804 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
805 "unexpected extent result for extent %d: %d",
806 i, advice[0].lla_lockahead_result);
813 return expected_lock_count;
816 /* Test sync requests, and matching with async requests */
817 static int test20(void)
819 struct llapi_lu_ladvise advice;
822 size_t write_size = 1024 * 1024;
824 char buf[write_size];
826 int expected_lock_count = 1;
828 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, 0600);
829 ASSERTF(fd >= 0, "open failed for '%s': %s",
830 mainpath, strerror(errno));
833 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
834 write_size - 1, true);
836 /* Manually set the result so we can verify it's being modified */
837 advice.lla_lockahead_result = 345678;
839 rc = llapi_ladvise(fd, 0, count, &advice);
841 "cannot lockahead '%s': %s", mainpath, strerror(errno));
842 ASSERTF(advice.lla_lockahead_result == 0,
843 "unexpected extent result: %d",
844 advice.lla_lockahead_result);
846 /* Ask again until we get the lock (status 1). */
847 for (i = 1; i < 100; i++) {
848 usleep(100000); /* 0.1 second */
849 advice.lla_lockahead_result = 456789;
850 rc = llapi_ladvise(fd, 0, count, &advice);
851 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
852 mainpath, strerror(errno));
854 if (advice.lla_lockahead_result > 0)
858 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
859 "unexpected extent result: %d",
860 advice.lla_lockahead_result);
862 /* Convert to a sync request on smaller range, should match and not
865 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
866 write_size - 1 - write_size/2, false);
868 advice.lla_lockahead_result = 456789;
869 rc = llapi_ladvise(fd, 0, count, &advice);
870 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
871 mainpath, strerror(errno));
872 /* Sync requests cannot give detailed results */
873 ASSERTF(advice.lla_lockahead_result == 0,
874 "unexpected extent result: %d",
875 advice.lla_lockahead_result);
877 /* Use an async request to test original lock is still present */
878 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
879 write_size - 1, true);
881 advice.lla_lockahead_result = 456789;
882 rc = llapi_ladvise(fd, 0, count, &advice);
883 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
884 mainpath, strerror(errno));
885 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
886 "unexpected extent result: %d",
887 advice.lla_lockahead_result);
889 memset(buf, 0xaa, write_size);
890 rc = write(fd, buf, write_size);
891 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
892 mainpath, strerror(errno));
896 return expected_lock_count;
899 /* Test sync requests, and conflict with async requests */
900 static int test21(void)
902 struct llapi_lu_ladvise advice;
905 size_t write_size = 1024 * 1024;
907 char buf[write_size];
909 int expected_lock_count = 1;
911 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, 0600);
912 ASSERTF(fd >= 0, "open failed for '%s': %s",
913 mainpath, strerror(errno));
916 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
917 write_size - 1, true);
919 /* Manually set the result so we can verify it's being modified */
920 advice.lla_lockahead_result = 345678;
922 rc = llapi_ladvise(fd, 0, count, &advice);
924 "cannot lockahead '%s': %s", mainpath, strerror(errno));
925 ASSERTF(advice.lla_lockahead_result == 0,
926 "unexpected extent result: %d",
927 advice.lla_lockahead_result);
929 /* Ask again until we get the lock (status 1). */
930 for (i = 1; i < 100; i++) {
931 usleep(100000); /* 0.1 second */
932 advice.lla_lockahead_result = 456789;
933 rc = llapi_ladvise(fd, 0, count, &advice);
934 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
935 mainpath, strerror(errno));
937 if (advice.lla_lockahead_result > 0)
941 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
942 "unexpected extent result: %d",
943 advice.lla_lockahead_result);
945 /* Convert to a sync request on larger range, should cancel existing
948 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
949 write_size*2 - 1, false);
951 advice.lla_lockahead_result = 456789;
952 rc = llapi_ladvise(fd, 0, count, &advice);
953 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
954 mainpath, strerror(errno));
955 /* Sync requests cannot give detailed results */
956 ASSERTF(advice.lla_lockahead_result == 0,
957 "unexpected extent result: %d",
958 advice.lla_lockahead_result);
960 /* Use an async request to test new lock is there */
961 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
962 write_size*2 - 1, true);
964 advice.lla_lockahead_result = 456789;
965 rc = llapi_ladvise(fd, 0, count, &advice);
966 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
967 mainpath, strerror(errno));
968 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
969 "unexpected extent result: %d",
970 advice.lla_lockahead_result);
972 memset(buf, 0xaa, write_size);
973 rc = write(fd, buf, write_size);
974 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
975 mainpath, strerror(errno));
979 return expected_lock_count;
982 /* Test various valid and invalid inputs */
983 static int test22(void)
985 struct llapi_lu_ladvise *advice;
992 fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, 0600);
993 ASSERTF(fd >= 0, "open failed for '%s': %s",
994 mainpath, strerror(errno));
996 /* A valid async request first */
997 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1000 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
1001 rc = llapi_ladvise(fd, 0, count, advice);
1002 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
1003 mainpath, strerror(errno));
1006 /* Valid request sync request */
1007 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1010 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, false);
1011 rc = llapi_ladvise(fd, 0, count, advice);
1012 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
1013 mainpath, strerror(errno));
1016 /* No actual block */
1017 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1020 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
1021 rc = llapi_ladvise(fd, 0, count, advice);
1022 ASSERTF(rc == -1 && errno == EINVAL,
1023 "unexpected return for no block lock: %d %s",
1024 rc, strerror(errno));
1027 /* end before start */
1028 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1029 start = 1024 * 1024;
1031 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
1032 rc = llapi_ladvise(fd, 0, count, advice);
1033 ASSERTF(rc == -1 && errno == EINVAL,
1034 "unexpected return for reversed block: %d %s",
1035 rc, strerror(errno));
1038 /* bogus lock mode - 0x65464 */
1039 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1042 setup_ladvise_lockahead(advice, 0x65464, 0, start, end, true);
1043 rc = llapi_ladvise(fd, 0, count, advice);
1044 ASSERTF(rc == -1 && errno == EINVAL,
1045 "unexpected return for bogus lock mode: %d %s",
1046 rc, strerror(errno));
1049 /* bogus flags, 0x80 */
1050 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1053 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0x80, start, end,
1055 rc = llapi_ladvise(fd, 0, count, advice);
1056 ASSERTF(rc == -1 && errno == EINVAL,
1057 "unexpected return for bogus flags: %u %d %s",
1058 0x80, rc, strerror(errno));
1061 /* bogus flags, 0xff - CEF_MASK */
1062 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1064 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xff, start, end,
1066 rc = llapi_ladvise(fd, 0, count, advice);
1067 ASSERTF(rc == -1 && errno == EINVAL,
1068 "unexpected return for bogus flags: %u %d %s",
1069 0xff, rc, strerror(errno));
1072 /* bogus flags, 0xffffffff */
1073 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1075 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xffffffff, start,
1077 rc = llapi_ladvise(fd, 0, count, advice);
1078 ASSERTF(rc == -1 && errno == EINVAL,
1079 "unexpected return for bogus flags: %u %d %s",
1080 0xffffffff, rc, strerror(errno));
1088 /* Do lockahead requests from two mount points & sanity check size
1090 * The key thing here is that client2 updates the size by writing, then asks
1091 * for another lock beyond that. That next lock is never used.
1092 * The bug (LU-11670) is that the glimpse for client1 will only check the
1093 * highest lock and miss the size update made by the lower lock.
1095 static int test23(void)
1097 struct llapi_lu_ladvise advice;
1098 size_t write_size = 1024 * 1024;
1099 char buf[write_size];
1100 const int count = 1;
1104 /* On second mount */
1109 fd = open(mainpath, O_CREAT | O_RDWR, 0600);
1110 ASSERTF(fd >= 0, "open failed for '%s': %s",
1111 mainpath, strerror(errno));
1113 /* mainpath2 is a different Lustre mount */
1114 fd2 = open(mainpath2, O_RDWR, 0600);
1115 ASSERTF(fd2 >= 0, "open failed for '%s': %s",
1116 mainpath2, strerror(errno));
1118 /* Lock + write MiB 1 from second client */
1119 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
1120 write_size - 1, true);
1122 /* Manually set the result so we can verify it's being modified */
1123 advice.lla_lockahead_result = 345678;
1125 rc = llapi_ladvise(fd2, 0, count, &advice);
1127 "cannot lockahead '%s': %s", mainpath2, strerror(errno));
1128 ASSERTF(advice.lla_lockahead_result == 0,
1129 "unexpected extent result: %d",
1130 advice.lla_lockahead_result);
1132 /* Ask again until we get the lock (status 1). */
1133 for (i = 1; i < 100; i++) {
1134 usleep(100000); /* 0.1 second */
1135 advice.lla_lockahead_result = 456789;
1136 rc = llapi_ladvise(fd2, 0, count, &advice);
1137 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
1138 mainpath2, strerror(errno));
1140 if (advice.lla_lockahead_result > 0)
1144 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
1145 "unexpected extent result: %d",
1146 advice.lla_lockahead_result);
1148 rc = write(fd2, buf, write_size);
1149 ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
1150 mainpath2, strerror(errno));
1152 /* Lock (but don't write) MiB 2 from second client */
1153 setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, write_size,
1154 2*write_size - 1, true);
1156 /* Manually set the result so we can verify it's being modified */
1157 advice.lla_lockahead_result = 345678;
1159 rc = llapi_ladvise(fd2, 0, count, &advice);
1161 "cannot lockahead '%s': %s", mainpath2, strerror(errno));
1162 ASSERTF(advice.lla_lockahead_result == 0,
1163 "unexpected extent result: %d",
1164 advice.lla_lockahead_result);
1166 /* Ask again until we get the lock (status 1). */
1167 for (i = 1; i < 100; i++) {
1168 usleep(100000); /* 0.1 second */
1169 advice.lla_lockahead_result = 456789;
1170 rc = llapi_ladvise(fd2, 0, count, &advice);
1171 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
1172 mainpath2, strerror(errno));
1174 if (advice.lla_lockahead_result > 0)
1178 ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
1179 "unexpected extent result: %d",
1180 advice.lla_lockahead_result);
1182 rc = fstat(fd, &sb);
1183 ASSERTF(!rc, "stat failed for '%s': %s",
1184 mainpath, strerror(errno));
1185 rc = fstat(fd2, &sb2);
1186 ASSERTF(!rc, "stat failed for '%s': %s",
1187 mainpath2, strerror(errno));
1189 ASSERTF(sb.st_size == sb2.st_size,
1190 "size on %s and %s differs: %lu vs %lu",
1191 mainpath, mainpath2, sb.st_size, sb2.st_size);
1193 ASSERTF(sb.st_size == write_size, "size %lu != bytes written (%lu)",
1194 sb.st_size, write_size);
1202 static void usage(char *prog)
1205 "Usage: %s [-d lustre_dir], [-D lustre_dir2] [-t test]\n",
1210 static void process_args(int argc, char *argv[])
1214 while ((c = getopt(argc, argv, "d:D:f:t:")) != -1) {
1220 lustre_dir = optarg;
1223 lustre_dir2 = optarg;
1226 single_test = atoi(optarg);
1230 fprintf(stderr, "Invalid option '%c'\n", optopt);
1237 int main(int argc, char *argv[])
1242 process_args(argc, argv);
1243 if (lustre_dir == NULL)
1244 lustre_dir = "/mnt/lustre";
1245 if (mainfile == NULL)
1246 mainfile = "lockahead_test_654";
1248 rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname);
1250 fprintf(stderr, "Error: '%s': not a Lustre filesystem\n",
1256 rc = llapi_search_mounts(lustre_dir2, 0, fsmountdir, fsname);
1259 "Error: '%s': not a Lustre filesystem\n",
1265 /* Play nice with Lustre test scripts. Non-line buffered output
1266 * stream under I/O redirection may appear incorrectly.
1268 setvbuf(stdout, NULL, _IOLBF, 0);
1270 /* Create a test filename and reuse it. Remove possibly old files. */
1271 rc = snprintf(mainpath, sizeof(mainpath), "%s/%s", lustre_dir,
1273 ASSERTF(rc > 0 && rc < sizeof(mainpath), "invalid name for mainpath");
1276 rc = snprintf(mainpath2, sizeof(mainpath2), "%s/%s",
1277 lustre_dir2, mainfile);
1278 ASSERTF(rc > 0 && rc < sizeof(mainpath2),
1279 "invalid name for mainpath2");
1284 switch (single_test) {
1299 /* Some tests require a second mount point */
1302 /* When running all the test cases, we can't use the return
1303 * from the last test case, as it might be non-zero to return
1304 * info, rather than for an error. Test cases assert and exit
1305 * if an error occurs.
1349 ASSERTF(lustre_dir2,
1350 "must provide second mount point for test 23");
1354 fprintf(stderr, "impossible value of single_test %d\n",