Whamcloud - gitweb
LU-6179 llite: Implement ladvise lockahead
[fs/lustre-release.git] / lustre / tests / lockahead_test.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
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).
15  *
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
19  *
20  * GPL HEADER END
21  */
22
23 /*
24  * Copyright 2016 Cray Inc. All rights reserved.
25  * Authors: Patrick Farrell, Frank Zago
26  *
27  * A few portions are extracted from llapi_layout_test.c
28  *
29  * The purpose of this test is to exercise the lockahead advice of ladvise.
30  *
31  * The program will exit as soon as a test fails.
32  */
33
34 #include <stdlib.h>
35 #include <errno.h>
36 #include <getopt.h>
37 #include <fcntl.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <unistd.h>
41 #include <poll.h>
42 #include <time.h>
43
44 #include <lustre/lustreapi.h>
45 #include <linux/lustre/lustre_idl.h>
46
47 #define ERROR(fmt, ...)                                                 \
48         fprintf(stderr, "%s: %s:%d: %s: " fmt "\n",                     \
49                 program_invocation_short_name, __FILE__, __LINE__,      \
50                 __func__, ## __VA_ARGS__);
51
52 #define DIE(fmt, ...)                           \
53         do {                                    \
54                 ERROR(fmt, ## __VA_ARGS__);     \
55                 exit(-1);               \
56         } while (0)
57
58 #define ASSERTF(cond, fmt, ...)                                         \
59         do {                                                            \
60                 if (!(cond))                                            \
61                         DIE("assertion '%s' failed: "fmt,               \
62                             #cond, ## __VA_ARGS__);                     \
63         } while (0)
64
65 #define PERFORM(testfn) \
66         do {                                                            \
67                 cleanup();                                              \
68                 fprintf(stderr, "Starting test " #testfn " at %lld\n",  \
69                         (unsigned long long)time(NULL));                \
70                 rc = testfn();                                          \
71                 fprintf(stderr, "Finishing test " #testfn " at %lld\n", \
72                         (unsigned long long)time(NULL));                \
73                 cleanup();                                              \
74         } while (0)
75
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";
79
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*/
83
84 /* Cleanup our test file. */
85 static void cleanup(void)
86 {
87         unlink(mainpath);
88 }
89
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)
93 {
94         advice->lla_advice = LU_LADVISE_LOCKAHEAD;
95         advice->lla_lockahead_mode = mode;
96         if (async)
97                 advice->lla_peradvice_flags = flags | LF_ASYNC;
98         else
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;
104 }
105
106 /* Test valid single lock ahead request */
107 static int test10(void)
108 {
109         struct llapi_lu_ladvise advice;
110         const int count = 1;
111         int fd;
112         size_t write_size = 1024 * 1024;
113         int rc;
114         char buf[write_size];
115
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));
119
120         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
121                                   write_size - 1, true);
122
123         /* Manually set the result so we can verify it's being modified */
124         advice.lla_lockahead_result = 345678;
125
126         rc = llapi_ladvise(fd, 0, count, &advice);
127         ASSERTF(rc == 0,
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);
132
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));
137
138
139         close(fd);
140
141         return 0;
142 }
143
144 /* Get lock, wait until lock is taken */
145 static int test11(void)
146 {
147         struct llapi_lu_ladvise advice;
148         const int count = 1;
149         int fd;
150         size_t write_size = 1024 * 1024;
151         int rc;
152         char buf[write_size];
153         int i;
154         int enqueue_requests = 0;
155
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));
159
160         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
161                                   write_size - 1, true);
162
163         /* Manually set the result so we can verify it's being modified */
164         advice.lla_lockahead_result = 345678;
165
166         rc = llapi_ladvise(fd, 0, count, &advice);
167         ASSERTF(rc == 0,
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);
172
173         enqueue_requests++;
174
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));
182
183                 if (advice.lla_lockahead_result > 0)
184                         break;
185
186                 enqueue_requests++;
187         }
188
189         ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
190                 "unexpected extent result: %d",
191                 advice.lla_lockahead_result);
192
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);
202         }
203
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));
208
209         close(fd);
210
211         return enqueue_requests;
212 }
213
214 /* Test with several times the same extent */
215 static int test12(void)
216 {
217         struct llapi_lu_ladvise *advice;
218         const int count = 10;
219         int fd;
220         size_t write_size = 1024 * 1024;
221         int rc;
222         char buf[write_size];
223         int i;
224         int expected_lock_count = 0;
225
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));
229
230         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
231
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;
236         }
237
238         rc = llapi_ladvise(fd, 0, count, advice);
239         ASSERTF(rc == 0,
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);
245         }
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;
249
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));
257
258                 if (advice[count-1].lla_lockahead_result > 0)
259                         break;
260         }
261
262         ASSERTF(advice[count-1].lla_lockahead_result == LLA_RESULT_SAME,
263                 "unexpected extent result: %d",
264                 advice[count-1].lla_lockahead_result);
265
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));
270
271         free(advice);
272         close(fd);
273
274         return expected_lock_count;
275 }
276
277 /* Grow a lock forward */
278 static int test13(void)
279 {
280         struct llapi_lu_ladvise *advice = NULL;
281         const int count = 1;
282         int fd;
283         size_t write_size = 1024 * 1024;
284         int rc;
285         char buf[write_size];
286         int i;
287         int expected_lock_count = 0;
288
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));
292
293         for (i = 0; i < 100; i++) {
294                 if (advice)
295                         free(advice);
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,
299                                         true);
300                 advice[0].lla_lockahead_result = 98674;
301
302                 rc = llapi_ladvise(fd, 0, count, advice);
303                 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
304                         mainpath,
305                         advice[0].lla_end,
306                         strerror(errno));
307
308                 ASSERTF(advice[0].lla_lockahead_result >= 0,
309                         "unexpected extent result for extent %d: %d",
310                         i, advice[0].lla_lockahead_result);
311
312                 expected_lock_count++;
313         }
314
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));
322
323                 if (advice[0].lla_lockahead_result > 0)
324                         break;
325         }
326
327         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
328                 "unexpected extent result: %d",
329                 advice[0].lla_lockahead_result);
330
331         free(advice);
332
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));
337
338         close(fd);
339
340         return expected_lock_count;
341 }
342
343 /* Grow a lock backward */
344 static int test14(void)
345 {
346         struct llapi_lu_ladvise *advice = NULL;
347         const int count = 1;
348         int fd;
349         size_t write_size = 1024 * 1024;
350         int rc;
351         char buf[write_size];
352         int i;
353         const int num_blocks = 100;
354         int expected_lock_count = 0;
355
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));
359
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;
363
364                 if (advice)
365                         free(advice);
366                 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
367                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
368                                         end, true);
369                 advice[0].lla_lockahead_result = 98674;
370
371                 rc = llapi_ladvise(fd, 0, count, advice);
372                 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
373                         mainpath,
374                         advice[0].lla_end,
375                         strerror(errno));
376
377                 ASSERTF(advice[0].lla_lockahead_result >= 0,
378                         "unexpected extent result for extent %d: %d",
379                         i, advice[0].lla_lockahead_result);
380
381                 expected_lock_count++;
382         }
383
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));
391
392                 if (advice[0].lla_lockahead_result > 0)
393                         break;
394         }
395
396         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
397                 "unexpected extent result: %d",
398                 advice[0].lla_lockahead_result);
399
400         free(advice);
401
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));
406
407         close(fd);
408
409         return expected_lock_count;
410 }
411
412 /* Request many locks at 10MiB intervals */
413 static int test15(void)
414 {
415         struct llapi_lu_ladvise *advice;
416         const int count = 1;
417         int fd;
418         size_t write_size = 1024 * 1024;
419         int rc;
420         char buf[write_size];
421         int i;
422         int expected_lock_count = 0;
423
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));
427
428         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
429
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;
435
436                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
437                                         end, true);
438
439                 advice[0].lla_lockahead_result = 345678;
440
441                 rc = llapi_ladvise(fd, 0, count, advice);
442
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++;
449         }
450
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));
458
459                 if (advice[0].lla_lockahead_result > 0)
460                         break;
461         }
462
463         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
464                 "unexpected extent result: %d",
465                 advice[0].lla_lockahead_result);
466
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. */
473
474         free(advice);
475
476         close(fd);
477
478         /* We have to map our expected return in to the range of valid return
479          * codes, 0-255. */
480         expected_lock_count = expected_lock_count/1000;
481
482         return expected_lock_count;
483 }
484
485 /* Use lockahead to verify behavior of ladvise locknoexpand */
486 static int test16(void)
487 {
488         struct llapi_lu_ladvise *advice;
489         struct llapi_lu_ladvise *advice_noexpand;
490         const int count = 1;
491         int fd;
492         size_t write_size = 1024 * 1024;
493         __u64 start = 0;
494         __u64 end = write_size - 1;
495         int rc;
496         char buf[write_size];
497         int expected_lock_count = 0;
498
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));
502
503         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
504         advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
505
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);
515
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);
525
526         /* Set noexpand */
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);
530
531         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
532                 mainpath, strerror(errno));
533
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++;
541
542         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
543
544         advice[0].lla_lockahead_result = 345678;
545
546         rc = llapi_ladvise(fd, 0, count, advice);
547
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);
553
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);
557
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++;
565
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 */
568
569         start = start + write_size;
570         end = end + write_size;
571         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
572
573         advice[0].lla_lockahead_result = 345678;
574
575         rc = llapi_ladvise(fd, 0, count, advice);
576
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);
582
583         free(advice);
584
585         close(fd);
586
587         return expected_lock_count;
588 }
589
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)
593 {
594         struct llapi_lu_ladvise *advice;
595         struct llapi_lu_ladvise *advice_noexpand;
596         const int count = 1;
597         int fd;
598         size_t write_size = 1024 * 1024;
599         __u64 start = 0;
600         __u64 end = write_size - 1;
601         int rc;
602         char buf[write_size];
603         int expected_lock_count = 0;
604
605         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC | O_NONBLOCK,
606                   S_IRUSR | S_IWUSR);
607         ASSERTF(fd >= 0, "open failed for '%s': %s",
608                 mainpath, strerror(errno));
609
610         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
611         advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
612
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);
622
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);
632
633         /* Set noexpand */
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);
637
638         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
639                 mainpath, strerror(errno));
640
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++;
648
649         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
650
651         advice[0].lla_lockahead_result = 345678;
652
653         rc = llapi_ladvise(fd, 0, count, advice);
654
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);
660
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);
664
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++;
672
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 */
675
676         start = start + write_size;
677         end = end + write_size;
678         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
679
680         advice[0].lla_lockahead_result = 345678;
681
682         rc = llapi_ladvise(fd, 0, count, advice);
683
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);
689
690         free(advice);
691
692         close(fd);
693
694         return expected_lock_count;
695 }
696
697 /* Test overlapping requests */
698 static int test18(void)
699 {
700         struct llapi_lu_ladvise *advice;
701         const int count = 1;
702         int fd;
703         int rc;
704         int i;
705         int expected_lock_count = 0;
706
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));
710
711         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
712
713         /* Overlapping locks - Should only end up with 1 */
714         for (i = 0; i < 10; i++) {
715                 __u64 start = i;
716                 __u64 end = start + 4096;
717
718                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
719                                         end, true);
720
721                 advice[0].lla_lockahead_result = 345678;
722
723                 rc = llapi_ladvise(fd, 0, count, advice);
724
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);
730         }
731         expected_lock_count = 1;
732
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,
738                                         true);
739                 rc = llapi_ladvise(fd, 0, count, advice);
740                 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
741                         mainpath, strerror(errno));
742
743                 if (advice[0].lla_lockahead_result > 0)
744                         break;
745         }
746
747         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
748                 "unexpected extent result: %d",
749                 advice[0].lla_lockahead_result);
750
751         free(advice);
752
753         close(fd);
754
755         return expected_lock_count;
756 }
757
758 /* Test that normal request blocks lock ahead requests */
759 static int test19(void)
760 {
761         struct llapi_lu_ladvise *advice;
762         const int count = 1;
763         int fd;
764         size_t write_size = 1024 * 1024;
765         int rc;
766         char buf[write_size];
767         int i;
768         int expected_lock_count = 0;
769
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));
773
774         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
775
776         /* This should create a lock on the whole file, which will block lock
777          * ahead requests. */
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));
782
783         expected_lock_count = 1;
784
785         /* These should all be blocked. */
786         for (i = 0; i < 10; i++) {
787                 __u64 start = i * 4096;
788                 __u64 end = start + 4096;
789
790                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
791                                         end, true);
792
793                 advice[0].lla_lockahead_result = 345678;
794
795                 rc = llapi_ladvise(fd, 0, count, advice);
796
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);
802         }
803
804         free(advice);
805
806         close(fd);
807
808         return expected_lock_count;
809 }
810
811 /* Test sync requests, and matching with async requests */
812 static int test20(void)
813 {
814         struct llapi_lu_ladvise advice;
815         const int count = 1;
816         int fd;
817         size_t write_size = 1024 * 1024;
818         int rc;
819         char buf[write_size];
820         int i;
821         int expected_lock_count = 1;
822
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));
826
827         /* Async request */
828         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
829                                 write_size - 1, true);
830
831         /* Manually set the result so we can verify it's being modified */
832         advice.lla_lockahead_result = 345678;
833
834         rc = llapi_ladvise(fd, 0, count, &advice);
835         ASSERTF(rc == 0,
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);
840
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));
848
849                 if (advice.lla_lockahead_result > 0)
850                         break;
851         }
852
853         ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
854                 "unexpected extent result: %d",
855                 advice.lla_lockahead_result);
856
857         /* Convert to a sync request on smaller range, should match and not
858          * cancel */
859         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
860                                 write_size - 1 - write_size/2, false);
861
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);
870
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);
874
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);
882
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));
887
888         close(fd);
889
890         return expected_lock_count;
891 }
892
893 /* Test sync requests, and conflict with async requests */
894 static int test21(void)
895 {
896         struct llapi_lu_ladvise advice;
897         const int count = 1;
898         int fd;
899         size_t write_size = 1024 * 1024;
900         int rc;
901         char buf[write_size];
902         int i;
903         int expected_lock_count = 1;
904
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));
908
909         /* Async request */
910         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
911                                 write_size - 1, true);
912
913         /* Manually set the result so we can verify it's being modified */
914         advice.lla_lockahead_result = 345678;
915
916         rc = llapi_ladvise(fd, 0, count, &advice);
917         ASSERTF(rc == 0,
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);
922
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));
930
931                 if (advice.lla_lockahead_result > 0)
932                         break;
933         }
934
935         ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
936                 "unexpected extent result: %d",
937                 advice.lla_lockahead_result);
938
939         /* Convert to a sync request on larger range, should cancel existing
940          * lock */
941         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
942                                 write_size*2 - 1, false);
943
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);
952
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);
956
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);
964
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));
969
970         close(fd);
971
972         return expected_lock_count;
973 }
974
975 /* Test various valid and invalid inputs */
976 static int test22(void)
977 {
978         struct llapi_lu_ladvise *advice;
979         const int count = 1;
980         int fd;
981         int rc;
982         size_t start = 0;
983         size_t end = 0;
984
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));
988
989         /* A valid async request first */
990         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
991         start = 0;
992         end = 1024*1024;
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));
997         free(advice);
998
999         /* Valid request sync request */
1000         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1001         start = 0;
1002         end = 1024*1024;
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));
1007         free(advice);
1008
1009         /* No actual block */
1010         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1011         start = 0;
1012         end = 0;
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));
1018         free(advice);
1019
1020         /* end before start */
1021         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1022         start = 1024 * 1024;
1023         end = 0;
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));
1029         free(advice);
1030
1031         /* bogus lock mode - 0x65464 */
1032         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1033         start = 0;
1034         end = 1024 * 1024;
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));
1040         free(advice);
1041
1042         /* bogus flags, 0x80 */
1043         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1044         start = 0;
1045         end = 1024 * 1024;
1046         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0x80, start, end,
1047                                 true);
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));
1052         free(advice);
1053
1054         /* bogus flags, 0xff - CEF_MASK */
1055         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1056         end = 1024 * 1024;
1057         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xff, start, end,
1058                                 true);
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));
1063         free(advice);
1064
1065         /* bogus flags, 0xffffffff */
1066         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1067         end = 1024 * 1024;
1068         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xffffffff, start,
1069                                 end, true);
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));
1074         free(advice);
1075
1076         close(fd);
1077
1078         return 0;
1079 }
1080
1081 static void usage(char *prog)
1082 {
1083         fprintf(stderr, "Usage: %s [-d lustre_dir], [-t single_test]\n", prog);
1084         exit(-1);
1085 }
1086
1087 static void process_args(int argc, char *argv[])
1088 {
1089         int c;
1090
1091         while ((c = getopt(argc, argv, "d:t:")) != -1) {
1092                 switch (c) {
1093                 case 'd':
1094                         lustre_dir = optarg;
1095                         break;
1096                 case 't':
1097                         single_test = atoi(optarg);
1098                         break;
1099                 case '?':
1100                 default:
1101                         fprintf(stderr, "Invalid option '%c'\n", optopt);
1102                         usage(argv[0]);
1103                         break;
1104                 }
1105         }
1106 }
1107
1108 int main(int argc, char *argv[])
1109 {
1110         char fsname[8];
1111         int rc;
1112
1113         process_args(argc, argv);
1114         if (lustre_dir == NULL)
1115                 lustre_dir = "/mnt/lustre";
1116
1117         rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname);
1118         if (rc != 0) {
1119                 fprintf(stderr, "Error: '%s': not a Lustre filesystem\n",
1120                         lustre_dir);
1121                 return -1;
1122         }
1123
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);
1127
1128         /* Create a test filename and reuse it. Remove possibly old files. */
1129         rc = snprintf(mainpath, sizeof(mainpath), "%s/%s", lustre_dir,
1130                       mainfile);
1131         ASSERTF(rc > 0 && rc < sizeof(mainpath), "invalid name for mainpath");
1132         cleanup();
1133
1134         atexit(cleanup);
1135
1136         switch (single_test) {
1137         case 0:
1138                 PERFORM(test10);
1139                 PERFORM(test11);
1140                 PERFORM(test12);
1141                 PERFORM(test13);
1142                 PERFORM(test14);
1143                 PERFORM(test15);
1144                 PERFORM(test16);
1145                 PERFORM(test17);
1146                 PERFORM(test18);
1147                 PERFORM(test19);
1148                 PERFORM(test20);
1149                 PERFORM(test21);
1150                 PERFORM(test22);
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. */
1155                 rc = 0;
1156                 break;
1157         case 10:
1158                 PERFORM(test10);
1159                 break;
1160         case 11:
1161                 PERFORM(test11);
1162                 break;
1163         case 12:
1164                 PERFORM(test12);
1165                 break;
1166         case 13:
1167                 PERFORM(test13);
1168                 break;
1169         case 14:
1170                 PERFORM(test14);
1171                 break;
1172         case 15:
1173                 PERFORM(test15);
1174                 break;
1175         case 16:
1176                 PERFORM(test16);
1177                 break;
1178         case 17:
1179                 PERFORM(test17);
1180                 break;
1181         case 18:
1182                 PERFORM(test18);
1183                 break;
1184         case 19:
1185                 PERFORM(test19);
1186                 break;
1187         case 20:
1188                 PERFORM(test20);
1189                 break;
1190         case 21:
1191                 PERFORM(test21);
1192                 break;
1193         case 22:
1194                 PERFORM(test22);
1195                 break;
1196         default:
1197                 fprintf(stderr, "impossible value of single_test %d\n",
1198                         single_test);
1199                 rc = -1;
1200                 break;
1201         }
1202
1203         return rc;
1204 }