Whamcloud - gitweb
LU-10657 utils: fd leak in mirror_split()
[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         } while (0)
74
75 /* Name of file/directory. Will be set once and will not change. */
76 static char mainpath[PATH_MAX];
77 static char *mainfile;
78
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*/
82
83 /* Cleanup our test file. */
84 static void cleanup(void)
85 {
86         unlink(mainpath);
87 }
88
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)
92 {
93         advice->lla_advice = LU_LADVISE_LOCKAHEAD;
94         advice->lla_lockahead_mode = mode;
95         if (async)
96                 advice->lla_peradvice_flags = flags | LF_ASYNC;
97         else
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;
103 }
104
105 /* Test valid single lock ahead request */
106 static int test10(void)
107 {
108         struct llapi_lu_ladvise advice;
109         const int count = 1;
110         int fd;
111         size_t write_size = 1024 * 1024;
112         int rc;
113         char buf[write_size];
114
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));
118
119         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
120                                   write_size - 1, true);
121
122         /* Manually set the result so we can verify it's being modified */
123         advice.lla_lockahead_result = 345678;
124
125         rc = llapi_ladvise(fd, 0, count, &advice);
126         ASSERTF(rc == 0,
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);
131
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));
136
137
138         close(fd);
139
140         return 0;
141 }
142
143 /* Get lock, wait until lock is taken */
144 static int test11(void)
145 {
146         struct llapi_lu_ladvise advice;
147         const int count = 1;
148         int fd;
149         size_t write_size = 1024 * 1024;
150         int rc;
151         char buf[write_size];
152         int i;
153         int enqueue_requests = 0;
154
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));
158
159         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
160                                   write_size - 1, true);
161
162         /* Manually set the result so we can verify it's being modified */
163         advice.lla_lockahead_result = 345678;
164
165         rc = llapi_ladvise(fd, 0, count, &advice);
166         ASSERTF(rc == 0,
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);
171
172         enqueue_requests++;
173
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));
181
182                 if (advice.lla_lockahead_result > 0)
183                         break;
184
185                 enqueue_requests++;
186         }
187
188         ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
189                 "unexpected extent result: %d",
190                 advice.lla_lockahead_result);
191
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);
201         }
202
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));
207
208         close(fd);
209
210         return enqueue_requests;
211 }
212
213 /* Test with several times the same extent */
214 static int test12(void)
215 {
216         struct llapi_lu_ladvise *advice;
217         const int count = 10;
218         int fd;
219         size_t write_size = 1024 * 1024;
220         int rc;
221         char buf[write_size];
222         int i;
223         int expected_lock_count = 0;
224
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));
228
229         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
230
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;
235         }
236
237         rc = llapi_ladvise(fd, 0, count, advice);
238         ASSERTF(rc == 0,
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);
244         }
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;
248
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));
256
257                 if (advice[count-1].lla_lockahead_result > 0)
258                         break;
259         }
260
261         ASSERTF(advice[count-1].lla_lockahead_result == LLA_RESULT_SAME,
262                 "unexpected extent result: %d",
263                 advice[count-1].lla_lockahead_result);
264
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));
269
270         free(advice);
271         close(fd);
272
273         return expected_lock_count;
274 }
275
276 /* Grow a lock forward */
277 static int test13(void)
278 {
279         struct llapi_lu_ladvise *advice = NULL;
280         const int count = 1;
281         int fd;
282         size_t write_size = 1024 * 1024;
283         int rc;
284         char buf[write_size];
285         int i;
286         int expected_lock_count = 0;
287
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));
291
292         for (i = 0; i < 100; i++) {
293                 if (advice)
294                         free(advice);
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,
298                                         true);
299                 advice[0].lla_lockahead_result = 98674;
300
301                 rc = llapi_ladvise(fd, 0, count, advice);
302                 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
303                         mainpath,
304                         advice[0].lla_end,
305                         strerror(errno));
306
307                 ASSERTF(advice[0].lla_lockahead_result >= 0,
308                         "unexpected extent result for extent %d: %d",
309                         i, advice[0].lla_lockahead_result);
310
311                 expected_lock_count++;
312         }
313
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));
321
322                 if (advice[0].lla_lockahead_result > 0)
323                         break;
324         }
325
326         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
327                 "unexpected extent result: %d",
328                 advice[0].lla_lockahead_result);
329
330         free(advice);
331
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));
336
337         close(fd);
338
339         return expected_lock_count;
340 }
341
342 /* Grow a lock backward */
343 static int test14(void)
344 {
345         struct llapi_lu_ladvise *advice = NULL;
346         const int count = 1;
347         int fd;
348         size_t write_size = 1024 * 1024;
349         int rc;
350         char buf[write_size];
351         int i;
352         const int num_blocks = 100;
353         int expected_lock_count = 0;
354
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));
358
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;
362
363                 if (advice)
364                         free(advice);
365                 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
366                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
367                                         end, true);
368                 advice[0].lla_lockahead_result = 98674;
369
370                 rc = llapi_ladvise(fd, 0, count, advice);
371                 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
372                         mainpath,
373                         advice[0].lla_end,
374                         strerror(errno));
375
376                 ASSERTF(advice[0].lla_lockahead_result >= 0,
377                         "unexpected extent result for extent %d: %d",
378                         i, advice[0].lla_lockahead_result);
379
380                 expected_lock_count++;
381         }
382
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));
390
391                 if (advice[0].lla_lockahead_result > 0)
392                         break;
393         }
394
395         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
396                 "unexpected extent result: %d",
397                 advice[0].lla_lockahead_result);
398
399         free(advice);
400
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));
405
406         close(fd);
407
408         return expected_lock_count;
409 }
410
411 /* Request many locks at 10MiB intervals */
412 static int test15(void)
413 {
414         struct llapi_lu_ladvise *advice;
415         const int count = 1;
416         int fd;
417         size_t write_size = 1024 * 1024;
418         int rc;
419         char buf[write_size];
420         int i;
421         int expected_lock_count = 0;
422
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));
426
427         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
428
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;
434
435                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
436                                         end, true);
437
438                 advice[0].lla_lockahead_result = 345678;
439
440                 rc = llapi_ladvise(fd, 0, count, advice);
441
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++;
448         }
449
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));
457
458                 if (advice[0].lla_lockahead_result > 0)
459                         break;
460         }
461
462         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
463                 "unexpected extent result: %d",
464                 advice[0].lla_lockahead_result);
465
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. */
472
473         free(advice);
474
475         close(fd);
476
477         /* We have to map our expected return in to the range of valid return
478          * codes, 0-255. */
479         expected_lock_count = expected_lock_count/100;
480
481         return expected_lock_count;
482 }
483
484 /* Use lockahead to verify behavior of ladvise locknoexpand */
485 static int test16(void)
486 {
487         struct llapi_lu_ladvise *advice;
488         struct llapi_lu_ladvise *advice_noexpand;
489         const int count = 1;
490         int fd;
491         size_t write_size = 1024 * 1024;
492         __u64 start = 0;
493         __u64 end = write_size - 1;
494         int rc;
495         char buf[write_size];
496         int expected_lock_count = 0;
497
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));
501
502         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
503         advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
504
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);
514
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);
524
525         /* Set noexpand */
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);
529
530         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
531                 mainpath, strerror(errno));
532
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++;
540
541         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
542
543         advice[0].lla_lockahead_result = 345678;
544
545         rc = llapi_ladvise(fd, 0, count, advice);
546
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);
552
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);
556
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++;
564
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 */
567
568         start = start + write_size;
569         end = end + write_size;
570         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
571
572         advice[0].lla_lockahead_result = 345678;
573
574         rc = llapi_ladvise(fd, 0, count, advice);
575
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);
581
582         free(advice);
583
584         close(fd);
585
586         return expected_lock_count;
587 }
588
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)
592 {
593         struct llapi_lu_ladvise *advice;
594         struct llapi_lu_ladvise *advice_noexpand;
595         const int count = 1;
596         int fd;
597         size_t write_size = 1024 * 1024;
598         __u64 start = 0;
599         __u64 end = write_size - 1;
600         int rc;
601         char buf[write_size];
602         int expected_lock_count = 0;
603
604         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC | O_NONBLOCK,
605                   S_IRUSR | S_IWUSR);
606         ASSERTF(fd >= 0, "open failed for '%s': %s",
607                 mainpath, strerror(errno));
608
609         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
610         advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
611
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);
621
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);
631
632         /* Set noexpand */
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);
636
637         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
638                 mainpath, strerror(errno));
639
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++;
647
648         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
649
650         advice[0].lla_lockahead_result = 345678;
651
652         rc = llapi_ladvise(fd, 0, count, advice);
653
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);
659
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);
663
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++;
671
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 */
674
675         start = start + write_size;
676         end = end + write_size;
677         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
678
679         advice[0].lla_lockahead_result = 345678;
680
681         rc = llapi_ladvise(fd, 0, count, advice);
682
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);
688
689         free(advice);
690
691         close(fd);
692
693         return expected_lock_count;
694 }
695
696 /* Test overlapping requests */
697 static int test18(void)
698 {
699         struct llapi_lu_ladvise *advice;
700         const int count = 1;
701         int fd;
702         int rc;
703         int i;
704         int expected_lock_count = 0;
705
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));
709
710         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
711
712         /* Overlapping locks - Should only end up with 1 */
713         for (i = 0; i < 10; i++) {
714                 __u64 start = i;
715                 __u64 end = start + 4096;
716
717                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
718                                         end, true);
719
720                 advice[0].lla_lockahead_result = 345678;
721
722                 rc = llapi_ladvise(fd, 0, count, advice);
723
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);
729         }
730         expected_lock_count = 1;
731
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,
737                                         true);
738                 rc = llapi_ladvise(fd, 0, count, advice);
739                 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
740                         mainpath, strerror(errno));
741
742                 if (advice[0].lla_lockahead_result > 0)
743                         break;
744         }
745
746         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
747                 "unexpected extent result: %d",
748                 advice[0].lla_lockahead_result);
749
750         free(advice);
751
752         close(fd);
753
754         return expected_lock_count;
755 }
756
757 /* Test that normal request blocks lock ahead requests */
758 static int test19(void)
759 {
760         struct llapi_lu_ladvise *advice;
761         const int count = 1;
762         int fd;
763         size_t write_size = 1024 * 1024;
764         int rc;
765         char buf[write_size];
766         int i;
767         int expected_lock_count = 0;
768
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));
772
773         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
774
775         /* This should create a lock on the whole file, which will block lock
776          * ahead requests. */
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));
781
782         expected_lock_count = 1;
783
784         /* These should all be blocked. */
785         for (i = 0; i < 10; i++) {
786                 __u64 start = i * 4096;
787                 __u64 end = start + 4096;
788
789                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
790                                         end, true);
791
792                 advice[0].lla_lockahead_result = 345678;
793
794                 rc = llapi_ladvise(fd, 0, count, advice);
795
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);
801         }
802
803         free(advice);
804
805         close(fd);
806
807         return expected_lock_count;
808 }
809
810 /* Test sync requests, and matching with async requests */
811 static int test20(void)
812 {
813         struct llapi_lu_ladvise advice;
814         const int count = 1;
815         int fd;
816         size_t write_size = 1024 * 1024;
817         int rc;
818         char buf[write_size];
819         int i;
820         int expected_lock_count = 1;
821
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));
825
826         /* Async request */
827         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
828                                 write_size - 1, true);
829
830         /* Manually set the result so we can verify it's being modified */
831         advice.lla_lockahead_result = 345678;
832
833         rc = llapi_ladvise(fd, 0, count, &advice);
834         ASSERTF(rc == 0,
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);
839
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));
847
848                 if (advice.lla_lockahead_result > 0)
849                         break;
850         }
851
852         ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
853                 "unexpected extent result: %d",
854                 advice.lla_lockahead_result);
855
856         /* Convert to a sync request on smaller range, should match and not
857          * cancel */
858         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
859                                 write_size - 1 - write_size/2, false);
860
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);
869
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);
873
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);
881
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));
886
887         close(fd);
888
889         return expected_lock_count;
890 }
891
892 /* Test sync requests, and conflict with async requests */
893 static int test21(void)
894 {
895         struct llapi_lu_ladvise advice;
896         const int count = 1;
897         int fd;
898         size_t write_size = 1024 * 1024;
899         int rc;
900         char buf[write_size];
901         int i;
902         int expected_lock_count = 1;
903
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));
907
908         /* Async request */
909         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
910                                 write_size - 1, true);
911
912         /* Manually set the result so we can verify it's being modified */
913         advice.lla_lockahead_result = 345678;
914
915         rc = llapi_ladvise(fd, 0, count, &advice);
916         ASSERTF(rc == 0,
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);
921
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));
929
930                 if (advice.lla_lockahead_result > 0)
931                         break;
932         }
933
934         ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
935                 "unexpected extent result: %d",
936                 advice.lla_lockahead_result);
937
938         /* Convert to a sync request on larger range, should cancel existing
939          * lock */
940         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
941                                 write_size*2 - 1, false);
942
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);
951
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);
955
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);
963
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));
968
969         close(fd);
970
971         return expected_lock_count;
972 }
973
974 /* Test various valid and invalid inputs */
975 static int test22(void)
976 {
977         struct llapi_lu_ladvise *advice;
978         const int count = 1;
979         int fd;
980         int rc;
981         size_t start = 0;
982         size_t end = 0;
983
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));
987
988         /* A valid async request first */
989         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
990         start = 0;
991         end = 1024*1024;
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));
996         free(advice);
997
998         /* Valid request sync request */
999         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1000         start = 0;
1001         end = 1024*1024;
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));
1006         free(advice);
1007
1008         /* No actual block */
1009         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1010         start = 0;
1011         end = 0;
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));
1017         free(advice);
1018
1019         /* end before start */
1020         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1021         start = 1024 * 1024;
1022         end = 0;
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));
1028         free(advice);
1029
1030         /* bogus lock mode - 0x65464 */
1031         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1032         start = 0;
1033         end = 1024 * 1024;
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));
1039         free(advice);
1040
1041         /* bogus flags, 0x80 */
1042         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1043         start = 0;
1044         end = 1024 * 1024;
1045         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0x80, start, end,
1046                                 true);
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));
1051         free(advice);
1052
1053         /* bogus flags, 0xff - CEF_MASK */
1054         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1055         end = 1024 * 1024;
1056         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xff, start, end,
1057                                 true);
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));
1062         free(advice);
1063
1064         /* bogus flags, 0xffffffff */
1065         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1066         end = 1024 * 1024;
1067         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xffffffff, start,
1068                                 end, true);
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));
1073         free(advice);
1074
1075         close(fd);
1076
1077         return 0;
1078 }
1079
1080 static void usage(char *prog)
1081 {
1082         fprintf(stderr, "Usage: %s [-d lustre_dir], [-t single_test]\n", prog);
1083         exit(-1);
1084 }
1085
1086 static void process_args(int argc, char *argv[])
1087 {
1088         int c;
1089
1090         while ((c = getopt(argc, argv, "d:f:t:")) != -1) {
1091                 switch (c) {
1092                 case 'f':
1093                         mainfile = optarg;
1094                         break;
1095                 case 'd':
1096                         lustre_dir = optarg;
1097                         break;
1098                 case 't':
1099                         single_test = atoi(optarg);
1100                         break;
1101                 case '?':
1102                 default:
1103                         fprintf(stderr, "Invalid option '%c'\n", optopt);
1104                         usage(argv[0]);
1105                         break;
1106                 }
1107         }
1108 }
1109
1110 int main(int argc, char *argv[])
1111 {
1112         char fsname[8];
1113         int rc;
1114
1115         process_args(argc, argv);
1116         if (lustre_dir == NULL)
1117                 lustre_dir = "/mnt/lustre";
1118         if (mainfile == NULL)
1119                 mainfile = "lockahead_test_654";
1120
1121         rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname);
1122         if (rc != 0) {
1123                 fprintf(stderr, "Error: '%s': not a Lustre filesystem\n",
1124                         lustre_dir);
1125                 return -1;
1126         }
1127
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);
1131
1132         /* Create a test filename and reuse it. Remove possibly old files. */
1133         rc = snprintf(mainpath, sizeof(mainpath), "%s/%s", lustre_dir,
1134                       mainfile);
1135         ASSERTF(rc > 0 && rc < sizeof(mainpath), "invalid name for mainpath");
1136         cleanup();
1137
1138         switch (single_test) {
1139         case 0:
1140                 PERFORM(test10);
1141                 PERFORM(test11);
1142                 PERFORM(test12);
1143                 PERFORM(test13);
1144                 PERFORM(test14);
1145                 PERFORM(test15);
1146                 PERFORM(test16);
1147                 PERFORM(test17);
1148                 PERFORM(test18);
1149                 PERFORM(test19);
1150                 PERFORM(test20);
1151                 PERFORM(test21);
1152                 PERFORM(test22);
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. */
1157                 rc = 0;
1158                 break;
1159         case 10:
1160                 PERFORM(test10);
1161                 break;
1162         case 11:
1163                 PERFORM(test11);
1164                 break;
1165         case 12:
1166                 PERFORM(test12);
1167                 break;
1168         case 13:
1169                 PERFORM(test13);
1170                 break;
1171         case 14:
1172                 PERFORM(test14);
1173                 break;
1174         case 15:
1175                 PERFORM(test15);
1176                 break;
1177         case 16:
1178                 PERFORM(test16);
1179                 break;
1180         case 17:
1181                 PERFORM(test17);
1182                 break;
1183         case 18:
1184                 PERFORM(test18);
1185                 break;
1186         case 19:
1187                 PERFORM(test19);
1188                 break;
1189         case 20:
1190                 PERFORM(test20);
1191                 break;
1192         case 21:
1193                 PERFORM(test21);
1194                 break;
1195         case 22:
1196                 PERFORM(test22);
1197                 break;
1198         default:
1199                 fprintf(stderr, "impossible value of single_test %d\n",
1200                         single_test);
1201                 rc = -1;
1202                 break;
1203         }
1204
1205         return rc;
1206 }