Whamcloud - gitweb
LU-14971 test: align mirror_io resync implementation
[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 /* Path to same file/directory on second mount */
78 static char mainpath2[PATH_MAX];
79 static char *mainfile;
80
81 static char fsmountdir[PATH_MAX];       /* Lustre mountpoint */
82 static char *lustre_dir;                /* Test directory inside Lustre */
83 static char *lustre_dir2;               /* Same dir but on second mountpoint */
84 static int single_test;                 /* Number of a single test to execute*/
85
86 /* Cleanup our test file. */
87 static void cleanup(void)
88 {
89         unlink(mainpath);
90 }
91
92 /* Trivial helper for one advice */
93 void setup_ladvise_lockahead(struct llapi_lu_ladvise *advice, int mode,
94                              int flags, size_t start, size_t end, bool async)
95 {
96         advice->lla_advice = LU_LADVISE_LOCKAHEAD;
97         advice->lla_lockahead_mode = mode;
98         if (async)
99                 advice->lla_peradvice_flags = flags | LF_ASYNC;
100         else
101                 advice->lla_peradvice_flags = flags;
102         advice->lla_start = start;
103         advice->lla_end = end;
104         advice->lla_value3 = 0;
105         advice->lla_value4 = 0;
106 }
107
108 /* Test valid single lock ahead request */
109 static int test10(void)
110 {
111         struct llapi_lu_ladvise advice;
112         const int count = 1;
113         int fd;
114         size_t write_size = 1024 * 1024;
115         int rc;
116         char buf[write_size];
117
118         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
119         ASSERTF(fd >= 0, "open failed for '%s': %s",
120                 mainpath, strerror(errno));
121
122         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
123                                   write_size - 1, true);
124
125         /* Manually set the result so we can verify it's being modified */
126         advice.lla_lockahead_result = 345678;
127
128         rc = llapi_ladvise(fd, 0, count, &advice);
129         ASSERTF(rc == 0,
130                 "cannot lockahead '%s': %s", mainpath, strerror(errno));
131         ASSERTF(advice.lla_lockahead_result == 0,
132                 "unexpected extent result: %d",
133                 advice.lla_lockahead_result);
134
135         memset(buf, 0xaa, write_size);
136         rc = write(fd, buf, write_size);
137         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
138                 mainpath, strerror(errno));
139
140
141         close(fd);
142
143         return 0;
144 }
145
146 /* Get lock, wait until lock is taken */
147 static int test11(void)
148 {
149         struct llapi_lu_ladvise advice;
150         const int count = 1;
151         int fd;
152         size_t write_size = 1024 * 1024;
153         int rc;
154         char buf[write_size];
155         int i;
156         int enqueue_requests = 0;
157
158         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
159         ASSERTF(fd >= 0, "open failed for '%s': %s",
160                 mainpath, strerror(errno));
161
162         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
163                                   write_size - 1, true);
164
165         /* Manually set the result so we can verify it's being modified */
166         advice.lla_lockahead_result = 345678;
167
168         rc = llapi_ladvise(fd, 0, count, &advice);
169         ASSERTF(rc == 0,
170                 "cannot lockahead '%s': %s", mainpath, strerror(errno));
171         ASSERTF(advice.lla_lockahead_result == 0,
172                 "unexpected extent result: %d",
173                 advice.lla_lockahead_result);
174
175         enqueue_requests++;
176
177         /* Ask again until we get the lock (status 1). */
178         for (i = 1; i < 100; i++) {
179                 usleep(100000); /* 0.1 second */
180                 advice.lla_lockahead_result = 456789;
181                 rc = llapi_ladvise(fd, 0, count, &advice);
182                 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
183                         mainpath, strerror(errno));
184
185                 if (advice.lla_lockahead_result > 0)
186                         break;
187
188                 enqueue_requests++;
189         }
190
191         ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
192                 "unexpected extent result: %d",
193                 advice.lla_lockahead_result);
194
195         /* Again. This time it is always there. */
196         for (i = 0; i < 100; i++) {
197                 advice.lla_lockahead_result = 456789;
198                 rc = llapi_ladvise(fd, 0, count, &advice);
199                 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
200                         mainpath, strerror(errno));
201                 ASSERTF(advice.lla_lockahead_result > 0,
202                         "unexpected extent result: %d",
203                         advice.lla_lockahead_result);
204         }
205
206         memset(buf, 0xaa, write_size);
207         rc = write(fd, buf, write_size);
208         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
209                 mainpath, strerror(errno));
210
211         close(fd);
212
213         return enqueue_requests;
214 }
215
216 /* Test with several times the same extent */
217 static int test12(void)
218 {
219         struct llapi_lu_ladvise *advice;
220         const int count = 10;
221         int fd;
222         size_t write_size = 1024 * 1024;
223         int rc;
224         char buf[write_size];
225         int i;
226         int expected_lock_count = 0;
227
228         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
229         ASSERTF(fd >= 0, "open failed for '%s': %s",
230                 mainpath, strerror(errno));
231
232         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
233
234         for (i = 0; i < count; i++) {
235                 setup_ladvise_lockahead(&(advice[i]), MODE_WRITE_USER, 0, 0,
236                                           write_size - 1, true);
237                 advice[i].lla_lockahead_result = 98674;
238         }
239
240         rc = llapi_ladvise(fd, 0, count, advice);
241         ASSERTF(rc == 0,
242                 "cannot lockahead '%s': %s", mainpath, strerror(errno));
243         for (i = 0; i < count; i++) {
244                 ASSERTF(advice[i].lla_lockahead_result >= 0,
245                         "unexpected extent result for extent %d: %d",
246                         i, advice[i].lla_lockahead_result);
247         }
248         /* Since all the requests are for the same extent, we should only have
249          * one lock at the end. */
250         expected_lock_count = 1;
251
252         /* Ask again until we get the locks. */
253         for (i = 1; i < 100; i++) {
254                 usleep(100000); /* 0.1 second */
255                 advice[count-1].lla_lockahead_result = 456789;
256                 rc = llapi_ladvise(fd, 0, count, advice);
257                 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
258                         mainpath, strerror(errno));
259
260                 if (advice[count-1].lla_lockahead_result > 0)
261                         break;
262         }
263
264         ASSERTF(advice[count-1].lla_lockahead_result == LLA_RESULT_SAME,
265                 "unexpected extent result: %d",
266                 advice[count-1].lla_lockahead_result);
267
268         memset(buf, 0xaa, write_size);
269         rc = write(fd, buf, write_size);
270         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
271                 mainpath, strerror(errno));
272
273         free(advice);
274         close(fd);
275
276         return expected_lock_count;
277 }
278
279 /* Grow a lock forward */
280 static int test13(void)
281 {
282         struct llapi_lu_ladvise *advice = NULL;
283         const int count = 1;
284         int fd;
285         size_t write_size = 1024 * 1024;
286         int rc;
287         char buf[write_size];
288         int i;
289         int expected_lock_count = 0;
290
291         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
292         ASSERTF(fd >= 0, "open failed for '%s': %s",
293                 mainpath, strerror(errno));
294
295         for (i = 0; i < 100; i++) {
296                 if (advice)
297                         free(advice);
298                 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
299                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0,
300                                         i * write_size, (i+1)*write_size - 1,
301                                         true);
302                 advice[0].lla_lockahead_result = 98674;
303
304                 rc = llapi_ladvise(fd, 0, count, advice);
305                 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
306                         mainpath,
307                         advice[0].lla_end,
308                         strerror(errno));
309
310                 ASSERTF(advice[0].lla_lockahead_result >= 0,
311                         "unexpected extent result for extent %d: %d",
312                         i, advice[0].lla_lockahead_result);
313
314                 expected_lock_count++;
315         }
316
317         /* Ask again until we get the lock. */
318         for (i = 1; i < 100; i++) {
319                 usleep(100000); /* 0.1 second */
320                 advice[0].lla_lockahead_result = 456789;
321                 rc = llapi_ladvise(fd, 0, count, advice);
322                 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
323                         mainpath, strerror(errno));
324
325                 if (advice[0].lla_lockahead_result > 0)
326                         break;
327         }
328
329         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
330                 "unexpected extent result: %d",
331                 advice[0].lla_lockahead_result);
332
333         free(advice);
334
335         memset(buf, 0xaa, write_size);
336         rc = write(fd, buf, write_size);
337         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
338                 mainpath, strerror(errno));
339
340         close(fd);
341
342         return expected_lock_count;
343 }
344
345 /* Grow a lock backward */
346 static int test14(void)
347 {
348         struct llapi_lu_ladvise *advice = NULL;
349         const int count = 1;
350         int fd;
351         size_t write_size = 1024 * 1024;
352         int rc;
353         char buf[write_size];
354         int i;
355         const int num_blocks = 100;
356         int expected_lock_count = 0;
357
358         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
359         ASSERTF(fd >= 0, "open failed for '%s': %s",
360                 mainpath, strerror(errno));
361
362         for (i = 0; i < num_blocks; i++) {
363                 size_t start = (num_blocks - i - 1) * write_size;
364                 size_t end = (num_blocks - i) * write_size - 1;
365
366                 if (advice)
367                         free(advice);
368                 advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
369                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
370                                         end, true);
371                 advice[0].lla_lockahead_result = 98674;
372
373                 rc = llapi_ladvise(fd, 0, count, advice);
374                 ASSERTF(rc == 0, "cannot lockahead '%s' at offset %llu: %s",
375                         mainpath,
376                         advice[0].lla_end,
377                         strerror(errno));
378
379                 ASSERTF(advice[0].lla_lockahead_result >= 0,
380                         "unexpected extent result for extent %d: %d",
381                         i, advice[0].lla_lockahead_result);
382
383                 expected_lock_count++;
384         }
385
386         /* Ask again until we get the lock. */
387         for (i = 1; i < 100; i++) {
388                 usleep(100000); /* 0.1 second */
389                 advice[0].lla_lockahead_result = 456789;
390                 rc = llapi_ladvise(fd, 0, count, advice);
391                 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
392                         mainpath, strerror(errno));
393
394                 if (advice[0].lla_lockahead_result > 0)
395                         break;
396         }
397
398         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
399                 "unexpected extent result: %d",
400                 advice[0].lla_lockahead_result);
401
402         free(advice);
403
404         memset(buf, 0xaa, write_size);
405         rc = write(fd, buf, write_size);
406         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
407                 mainpath, strerror(errno));
408
409         close(fd);
410
411         return expected_lock_count;
412 }
413
414 /* Request many locks at 10MiB intervals */
415 static int test15(void)
416 {
417         struct llapi_lu_ladvise *advice;
418         const int count = 1;
419         int fd;
420         size_t write_size = 1024 * 1024;
421         int rc;
422         char buf[write_size];
423         int i;
424         int expected_lock_count = 0;
425
426         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
427         ASSERTF(fd >= 0, "open failed for '%s': %s",
428                 mainpath, strerror(errno));
429
430         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
431
432         for (i = 0; i < 500; i++) {
433                 /* The 'UL' designators are required to avoid undefined
434                  * behavior which GCC turns in to an infinite loop */
435                 __u64 start = i * 1024UL * 1024UL * 10UL;
436                 __u64 end = start + 1;
437
438                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
439                                         end, true);
440
441                 advice[0].lla_lockahead_result = 345678;
442
443                 rc = llapi_ladvise(fd, 0, count, advice);
444
445                 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
446                         mainpath, strerror(errno));
447                 ASSERTF(advice[0].lla_lockahead_result >= 0,
448                         "unexpected extent result for extent %d: %d",
449                         i, advice[0].lla_lockahead_result);
450                 expected_lock_count++;
451         }
452
453         /* Ask again until we get the lock. */
454         for (i = 1; i < 100; i++) {
455                 usleep(100000); /* 0.1 second */
456                 advice[0].lla_lockahead_result = 456789;
457                 rc = llapi_ladvise(fd, 0, count, advice);
458                 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
459                         mainpath, strerror(errno));
460
461                 if (advice[0].lla_lockahead_result > 0)
462                         break;
463         }
464
465         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
466                 "unexpected extent result: %d",
467                 advice[0].lla_lockahead_result);
468
469         memset(buf, 0xaa, write_size);
470         rc = write(fd, buf, write_size);
471         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
472                 mainpath, strerror(errno));
473         /* The write should cancel the first lock (which was too small)
474          * and create one of its own, so the net effect on lock count is 0. */
475
476         free(advice);
477
478         close(fd);
479
480         /* We have to map our expected return in to the range of valid return
481          * codes, 0-255. */
482         expected_lock_count = expected_lock_count/100;
483
484         return expected_lock_count;
485 }
486
487 /* Use lockahead to verify behavior of ladvise locknoexpand */
488 static int test16(void)
489 {
490         struct llapi_lu_ladvise *advice;
491         struct llapi_lu_ladvise *advice_noexpand;
492         const int count = 1;
493         int fd;
494         size_t write_size = 1024 * 1024;
495         __u64 start = 0;
496         __u64 end = write_size - 1;
497         int rc;
498         char buf[write_size];
499         int expected_lock_count = 0;
500
501         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
502         ASSERTF(fd >= 0, "open failed for '%s': %s",
503                 mainpath, strerror(errno));
504
505         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
506         advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
507
508         /* First ask for a read lock, which will conflict with the write */
509         setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, false);
510         advice[0].lla_lockahead_result = 345678;
511         rc = llapi_ladvise(fd, 0, count, advice);
512         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
513                 mainpath, strerror(errno));
514         ASSERTF(advice[0].lla_lockahead_result == 0,
515                 "unexpected extent result for extent: %d",
516                 advice[0].lla_lockahead_result);
517
518         /* Use an async request to verify we got the read lock we asked for */
519         setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, true);
520         advice[0].lla_lockahead_result = 345678;
521         rc = llapi_ladvise(fd, 0, count, advice);
522         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
523                 mainpath, strerror(errno));
524         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
525                 "unexpected extent result for extent: %d",
526                 advice[0].lla_lockahead_result);
527
528         /* Set noexpand */
529         advice_noexpand[0].lla_advice = LU_LADVISE_LOCKNOEXPAND;
530         advice_noexpand[0].lla_peradvice_flags = 0;
531         rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
532
533         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
534                 mainpath, strerror(errno));
535
536         /* This write should generate a lock on exactly "write_size" bytes */
537         memset(buf, 0xaa, write_size);
538         rc = write(fd, buf, write_size);
539         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
540                 mainpath, strerror(errno));
541         /* Write should create one LDLM lock */
542         expected_lock_count++;
543
544         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
545
546         advice[0].lla_lockahead_result = 345678;
547
548         rc = llapi_ladvise(fd, 0, count, advice);
549
550         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
551                 mainpath, strerror(errno));
552         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
553                 "unexpected extent result for extent: %d",
554                 advice[0].lla_lockahead_result);
555
556         /* Now, disable locknoexpand and try writing again. */
557         advice_noexpand[0].lla_peradvice_flags = LF_UNSET;
558         rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
559
560         /* This write should get an expanded lock */
561         memset(buf, 0xaa, write_size);
562         rc = write(fd, buf, write_size);
563         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
564                 mainpath, strerror(errno));
565         /* Write should create one LDLM lock */
566         expected_lock_count++;
567
568         /* Verify it didn't get a lock on just the bytes it wrote.*/
569         usleep(100000); /* 0.1 second, plenty of time to get the lock */
570
571         start = start + write_size;
572         end = end + write_size;
573         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
574
575         advice[0].lla_lockahead_result = 345678;
576
577         rc = llapi_ladvise(fd, 0, count, advice);
578
579         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
580                 mainpath, strerror(errno));
581         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
582                 "unexpected extent result for extent %d",
583                 advice[0].lla_lockahead_result);
584
585         free(advice);
586
587         close(fd);
588
589         return expected_lock_count;
590 }
591
592 /* Use lockahead to verify behavior of ladvise locknoexpand, with O_NONBLOCK.
593  * There should be no change in behavior. */
594 static int test17(void)
595 {
596         struct llapi_lu_ladvise *advice;
597         struct llapi_lu_ladvise *advice_noexpand;
598         const int count = 1;
599         int fd;
600         size_t write_size = 1024 * 1024;
601         __u64 start = 0;
602         __u64 end = write_size - 1;
603         int rc;
604         char buf[write_size];
605         int expected_lock_count = 0;
606
607         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC | O_NONBLOCK,
608                   S_IRUSR | S_IWUSR);
609         ASSERTF(fd >= 0, "open failed for '%s': %s",
610                 mainpath, strerror(errno));
611
612         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
613         advice_noexpand = malloc(sizeof(struct llapi_lu_ladvise));
614
615         /* First ask for a read lock, which will conflict with the write */
616         setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, false);
617         advice[0].lla_lockahead_result = 345678;
618         rc = llapi_ladvise(fd, 0, count, advice);
619         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
620                 mainpath, strerror(errno));
621         ASSERTF(advice[0].lla_lockahead_result == 0,
622                 "unexpected extent result for extent: %d",
623                 advice[0].lla_lockahead_result);
624
625         /* Use an async request to verify we got the read lock we asked for */
626         setup_ladvise_lockahead(advice, MODE_READ_USER, 0, start, end, true);
627         advice[0].lla_lockahead_result = 345678;
628         rc = llapi_ladvise(fd, 0, count, advice);
629         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
630                 mainpath, strerror(errno));
631         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
632                 "unexpected extent result for extent: %d",
633                 advice[0].lla_lockahead_result);
634
635         /* Set noexpand */
636         advice_noexpand[0].lla_advice = LU_LADVISE_LOCKNOEXPAND;
637         advice_noexpand[0].lla_peradvice_flags = 0;
638         rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
639
640         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
641                 mainpath, strerror(errno));
642
643         /* This write should generate a lock on exactly "write_size" bytes */
644         memset(buf, 0xaa, write_size);
645         rc = write(fd, buf, write_size);
646         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
647                 mainpath, strerror(errno));
648         /* Write should create one LDLM lock */
649         expected_lock_count++;
650
651         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
652
653         advice[0].lla_lockahead_result = 345678;
654
655         rc = llapi_ladvise(fd, 0, count, advice);
656
657         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
658                 mainpath, strerror(errno));
659         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
660                 "unexpected extent result for extent: %d",
661                 advice[0].lla_lockahead_result);
662
663         /* Now, disable locknoexpand and try writing again. */
664         advice_noexpand[0].lla_peradvice_flags = LF_UNSET;
665         rc = llapi_ladvise(fd, 0, 1, advice_noexpand);
666
667         /* This write should get an expanded lock */
668         memset(buf, 0xaa, write_size);
669         rc = write(fd, buf, write_size);
670         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
671                 mainpath, strerror(errno));
672         /* Write should create one LDLM lock */
673         expected_lock_count++;
674
675         /* Verify it didn't get a lock on just the bytes it wrote.*/
676         usleep(100000); /* 0.1 second, plenty of time to get the lock */
677
678         start = start + write_size;
679         end = end + write_size;
680         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
681
682         advice[0].lla_lockahead_result = 345678;
683
684         rc = llapi_ladvise(fd, 0, count, advice);
685
686         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
687                 mainpath, strerror(errno));
688         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
689                 "unexpected extent result for extent %d",
690                 advice[0].lla_lockahead_result);
691
692         free(advice);
693
694         close(fd);
695
696         return expected_lock_count;
697 }
698
699 /* Test overlapping requests */
700 static int test18(void)
701 {
702         struct llapi_lu_ladvise *advice;
703         const int count = 1;
704         int fd;
705         int rc;
706         int i;
707         int expected_lock_count = 0;
708
709         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
710         ASSERTF(fd >= 0, "open failed for '%s': %s",
711                 mainpath, strerror(errno));
712
713         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
714
715         /* Overlapping locks - Should only end up with 1 */
716         for (i = 0; i < 10; i++) {
717                 __u64 start = i;
718                 __u64 end = start + 4096;
719
720                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
721                                         end, true);
722
723                 advice[0].lla_lockahead_result = 345678;
724
725                 rc = llapi_ladvise(fd, 0, count, advice);
726
727                 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
728                         mainpath, strerror(errno));
729                 ASSERTF(advice[0].lla_lockahead_result >= 0,
730                         "unexpected extent result for extent %d: %d",
731                         i, advice[0].lla_lockahead_result);
732         }
733         expected_lock_count = 1;
734
735         /* Ask again until we get the lock. */
736         for (i = 1; i < 100; i++) {
737                 usleep(100000); /* 0.1 second */
738                 advice[0].lla_lockahead_result = 456789;
739                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, 0, 4096,
740                                         true);
741                 rc = llapi_ladvise(fd, 0, count, advice);
742                 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
743                         mainpath, strerror(errno));
744
745                 if (advice[0].lla_lockahead_result > 0)
746                         break;
747         }
748
749         ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_SAME,
750                 "unexpected extent result: %d",
751                 advice[0].lla_lockahead_result);
752
753         free(advice);
754
755         close(fd);
756
757         return expected_lock_count;
758 }
759
760 /* Test that normal request blocks lock ahead requests */
761 static int test19(void)
762 {
763         struct llapi_lu_ladvise *advice;
764         const int count = 1;
765         int fd;
766         size_t write_size = 1024 * 1024;
767         int rc;
768         char buf[write_size];
769         int i;
770         int expected_lock_count = 0;
771
772         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
773         ASSERTF(fd >= 0, "open failed for '%s': %s",
774                 mainpath, strerror(errno));
775
776         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
777
778         /* This should create a lock on the whole file, which will block lock
779          * ahead requests. */
780         memset(buf, 0xaa, write_size);
781         rc = write(fd, buf, write_size);
782         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
783                 mainpath, strerror(errno));
784
785         expected_lock_count = 1;
786
787         /* These should all be blocked. */
788         for (i = 0; i < 10; i++) {
789                 __u64 start = i * 4096;
790                 __u64 end = start + 4096;
791
792                 setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start,
793                                         end, true);
794
795                 advice[0].lla_lockahead_result = 345678;
796
797                 rc = llapi_ladvise(fd, 0, count, advice);
798
799                 ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
800                         mainpath, strerror(errno));
801                 ASSERTF(advice[0].lla_lockahead_result == LLA_RESULT_DIFFERENT,
802                         "unexpected extent result for extent %d: %d",
803                         i, advice[0].lla_lockahead_result);
804         }
805
806         free(advice);
807
808         close(fd);
809
810         return expected_lock_count;
811 }
812
813 /* Test sync requests, and matching with async requests */
814 static int test20(void)
815 {
816         struct llapi_lu_ladvise advice;
817         const int count = 1;
818         int fd;
819         size_t write_size = 1024 * 1024;
820         int rc;
821         char buf[write_size];
822         int i;
823         int expected_lock_count = 1;
824
825         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
826         ASSERTF(fd >= 0, "open failed for '%s': %s",
827                 mainpath, strerror(errno));
828
829         /* Async request */
830         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
831                                 write_size - 1, true);
832
833         /* Manually set the result so we can verify it's being modified */
834         advice.lla_lockahead_result = 345678;
835
836         rc = llapi_ladvise(fd, 0, count, &advice);
837         ASSERTF(rc == 0,
838                 "cannot lockahead '%s': %s", mainpath, strerror(errno));
839         ASSERTF(advice.lla_lockahead_result == 0,
840                 "unexpected extent result: %d",
841                 advice.lla_lockahead_result);
842
843         /* Ask again until we get the lock (status 1). */
844         for (i = 1; i < 100; i++) {
845                 usleep(100000); /* 0.1 second */
846                 advice.lla_lockahead_result = 456789;
847                 rc = llapi_ladvise(fd, 0, count, &advice);
848                 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
849                         mainpath, strerror(errno));
850
851                 if (advice.lla_lockahead_result > 0)
852                         break;
853         }
854
855         ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
856                 "unexpected extent result: %d",
857                 advice.lla_lockahead_result);
858
859         /* Convert to a sync request on smaller range, should match and not
860          * cancel */
861         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
862                                 write_size - 1 - write_size/2, false);
863
864         advice.lla_lockahead_result = 456789;
865         rc = llapi_ladvise(fd, 0, count, &advice);
866         ASSERTF(rc == 0, "cannot lockahead '%s': %s",
867                 mainpath, strerror(errno));
868         /* Sync requests cannot give detailed results */
869         ASSERTF(advice.lla_lockahead_result == 0,
870                 "unexpected extent result: %d",
871                 advice.lla_lockahead_result);
872
873         /* Use an async request to test original lock is still present */
874         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
875                                 write_size - 1, true);
876
877         advice.lla_lockahead_result = 456789;
878         rc = llapi_ladvise(fd, 0, count, &advice);
879         ASSERTF(rc == 0, "cannot lockahead '%s': %s",
880                 mainpath, strerror(errno));
881         ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
882                 "unexpected extent result: %d",
883                 advice.lla_lockahead_result);
884
885         memset(buf, 0xaa, write_size);
886         rc = write(fd, buf, write_size);
887         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
888                 mainpath, strerror(errno));
889
890         close(fd);
891
892         return expected_lock_count;
893 }
894
895 /* Test sync requests, and conflict with async requests */
896 static int test21(void)
897 {
898         struct llapi_lu_ladvise advice;
899         const int count = 1;
900         int fd;
901         size_t write_size = 1024 * 1024;
902         int rc;
903         char buf[write_size];
904         int i;
905         int expected_lock_count = 1;
906
907         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
908         ASSERTF(fd >= 0, "open failed for '%s': %s",
909                 mainpath, strerror(errno));
910
911         /* Async request */
912         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
913                                 write_size - 1, true);
914
915         /* Manually set the result so we can verify it's being modified */
916         advice.lla_lockahead_result = 345678;
917
918         rc = llapi_ladvise(fd, 0, count, &advice);
919         ASSERTF(rc == 0,
920                 "cannot lockahead '%s': %s", mainpath, strerror(errno));
921         ASSERTF(advice.lla_lockahead_result == 0,
922                 "unexpected extent result: %d",
923                 advice.lla_lockahead_result);
924
925         /* Ask again until we get the lock (status 1). */
926         for (i = 1; i < 100; i++) {
927                 usleep(100000); /* 0.1 second */
928                 advice.lla_lockahead_result = 456789;
929                 rc = llapi_ladvise(fd, 0, count, &advice);
930                 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
931                         mainpath, strerror(errno));
932
933                 if (advice.lla_lockahead_result > 0)
934                         break;
935         }
936
937         ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
938                 "unexpected extent result: %d",
939                 advice.lla_lockahead_result);
940
941         /* Convert to a sync request on larger range, should cancel existing
942          * lock */
943         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
944                                 write_size*2 - 1, false);
945
946         advice.lla_lockahead_result = 456789;
947         rc = llapi_ladvise(fd, 0, count, &advice);
948         ASSERTF(rc == 0, "cannot lockahead '%s': %s",
949                 mainpath, strerror(errno));
950         /* Sync requests cannot give detailed results */
951         ASSERTF(advice.lla_lockahead_result == 0,
952                 "unexpected extent result: %d",
953                 advice.lla_lockahead_result);
954
955         /* Use an async request to test new lock is there */
956         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
957                                 write_size*2 - 1, true);
958
959         advice.lla_lockahead_result = 456789;
960         rc = llapi_ladvise(fd, 0, count, &advice);
961         ASSERTF(rc == 0, "cannot lockahead '%s': %s",
962                 mainpath, strerror(errno));
963         ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
964                 "unexpected extent result: %d",
965                 advice.lla_lockahead_result);
966
967         memset(buf, 0xaa, write_size);
968         rc = write(fd, buf, write_size);
969         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
970                 mainpath, strerror(errno));
971
972         close(fd);
973
974         return expected_lock_count;
975 }
976
977 /* Test various valid and invalid inputs */
978 static int test22(void)
979 {
980         struct llapi_lu_ladvise *advice;
981         const int count = 1;
982         int fd;
983         int rc;
984         size_t start = 0;
985         size_t end = 0;
986
987         fd = open(mainpath, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
988         ASSERTF(fd >= 0, "open failed for '%s': %s",
989                 mainpath, strerror(errno));
990
991         /* A valid async request first */
992         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
993         start = 0;
994         end = 1024*1024;
995         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
996         rc = llapi_ladvise(fd, 0, count, advice);
997         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
998                 mainpath, strerror(errno));
999         free(advice);
1000
1001         /* Valid request sync request */
1002         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1003         start = 0;
1004         end = 1024*1024;
1005         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, false);
1006         rc = llapi_ladvise(fd, 0, count, advice);
1007         ASSERTF(rc == 0, "cannot lockahead '%s' : %s",
1008                 mainpath, strerror(errno));
1009         free(advice);
1010
1011         /* No actual block */
1012         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1013         start = 0;
1014         end = 0;
1015         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
1016         rc = llapi_ladvise(fd, 0, count, advice);
1017         ASSERTF(rc == -1 && errno == EINVAL,
1018                 "unexpected return for no block lock: %d %s",
1019                 rc, strerror(errno));
1020         free(advice);
1021
1022         /* end before start */
1023         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1024         start = 1024 * 1024;
1025         end = 0;
1026         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0, start, end, true);
1027         rc = llapi_ladvise(fd, 0, count, advice);
1028         ASSERTF(rc == -1 && errno == EINVAL,
1029                 "unexpected return for reversed block: %d %s",
1030                 rc, strerror(errno));
1031         free(advice);
1032
1033         /* bogus lock mode - 0x65464 */
1034         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1035         start = 0;
1036         end = 1024 * 1024;
1037         setup_ladvise_lockahead(advice, 0x65464, 0, start, end, true);
1038         rc = llapi_ladvise(fd, 0, count, advice);
1039         ASSERTF(rc == -1 && errno == EINVAL,
1040                 "unexpected return for bogus lock mode: %d %s",
1041                 rc, strerror(errno));
1042         free(advice);
1043
1044         /* bogus flags, 0x80 */
1045         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1046         start = 0;
1047         end = 1024 * 1024;
1048         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0x80, start, end,
1049                                 true);
1050         rc = llapi_ladvise(fd, 0, count, advice);
1051         ASSERTF(rc == -1 && errno == EINVAL,
1052                 "unexpected return for bogus flags: %u %d %s",
1053                 0x80, rc, strerror(errno));
1054         free(advice);
1055
1056         /* bogus flags, 0xff - CEF_MASK */
1057         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1058         end = 1024 * 1024;
1059         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xff, start, end,
1060                                 true);
1061         rc = llapi_ladvise(fd, 0, count, advice);
1062         ASSERTF(rc == -1 && errno == EINVAL,
1063                 "unexpected return for bogus flags: %u %d %s",
1064                 0xff, rc, strerror(errno));
1065         free(advice);
1066
1067         /* bogus flags, 0xffffffff */
1068         advice = malloc(sizeof(struct llapi_lu_ladvise)*count);
1069         end = 1024 * 1024;
1070         setup_ladvise_lockahead(advice, MODE_WRITE_USER, 0xffffffff, start,
1071                                 end, true);
1072         rc = llapi_ladvise(fd, 0, count, advice);
1073         ASSERTF(rc == -1 && errno == EINVAL,
1074                 "unexpected return for bogus flags: %u %d %s",
1075                 0xffffffff, rc, strerror(errno));
1076         free(advice);
1077
1078         close(fd);
1079
1080         return 0;
1081 }
1082
1083 /* Do lockahead requests from two mount points & sanity check size
1084  *
1085  * The key thing here is that client2 updates the size by writing, then asks
1086  * for another lock beyond that.  That next lock is never used.
1087  * The bug (LU-11670) is that the glimpse for client1 will only check the
1088  * highest lock and miss the size update made by the lower lock.
1089  */
1090 static int test23(void)
1091 {
1092         struct llapi_lu_ladvise advice;
1093         size_t write_size = 1024 * 1024;
1094         char buf[write_size];
1095         const int count = 1;
1096         struct stat sb;
1097         struct stat sb2;
1098         int fd;
1099         /* On second mount */
1100         int fd2;
1101         int rc;
1102         int i;
1103
1104         fd = open(mainpath, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
1105         ASSERTF(fd >= 0, "open failed for '%s': %s",
1106                 mainpath, strerror(errno));
1107
1108         /* mainpath2 is a different Lustre mount */
1109         fd2 = open(mainpath2, O_RDWR, S_IRUSR | S_IWUSR);
1110         ASSERTF(fd2 >= 0, "open failed for '%s': %s",
1111                 mainpath2, strerror(errno));
1112
1113         /* Lock + write MiB 1 from second client */
1114         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, 0,
1115                                 write_size - 1, true);
1116
1117         /* Manually set the result so we can verify it's being modified */
1118         advice.lla_lockahead_result = 345678;
1119
1120         rc = llapi_ladvise(fd2, 0, count, &advice);
1121         ASSERTF(rc == 0,
1122                 "cannot lockahead '%s': %s", mainpath2, strerror(errno));
1123         ASSERTF(advice.lla_lockahead_result == 0,
1124                 "unexpected extent result: %d",
1125                 advice.lla_lockahead_result);
1126
1127         /* Ask again until we get the lock (status 1). */
1128         for (i = 1; i < 100; i++) {
1129                 usleep(100000); /* 0.1 second */
1130                 advice.lla_lockahead_result = 456789;
1131                 rc = llapi_ladvise(fd2, 0, count, &advice);
1132                 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
1133                         mainpath2, strerror(errno));
1134
1135                 if (advice.lla_lockahead_result > 0)
1136                         break;
1137         }
1138
1139         ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
1140                 "unexpected extent result: %d",
1141                 advice.lla_lockahead_result);
1142
1143         rc = write(fd2, buf, write_size);
1144         ASSERTF(rc == sizeof(buf), "write failed for '%s': %s",
1145                 mainpath2, strerror(errno));
1146
1147         /* Lock (but don't write) MiB 2 from second client */
1148         setup_ladvise_lockahead(&advice, MODE_WRITE_USER, 0, write_size,
1149                                 2*write_size - 1, true);
1150
1151         /* Manually set the result so we can verify it's being modified */
1152         advice.lla_lockahead_result = 345678;
1153
1154         rc = llapi_ladvise(fd2, 0, count, &advice);
1155         ASSERTF(rc == 0,
1156                 "cannot lockahead '%s': %s", mainpath2, strerror(errno));
1157         ASSERTF(advice.lla_lockahead_result == 0,
1158                 "unexpected extent result: %d",
1159                 advice.lla_lockahead_result);
1160
1161         /* Ask again until we get the lock (status 1). */
1162         for (i = 1; i < 100; i++) {
1163                 usleep(100000); /* 0.1 second */
1164                 advice.lla_lockahead_result = 456789;
1165                 rc = llapi_ladvise(fd2, 0, count, &advice);
1166                 ASSERTF(rc == 0, "cannot lockahead '%s': %s",
1167                         mainpath2, strerror(errno));
1168
1169                 if (advice.lla_lockahead_result > 0)
1170                         break;
1171         }
1172
1173         ASSERTF(advice.lla_lockahead_result == LLA_RESULT_SAME,
1174                 "unexpected extent result: %d",
1175                 advice.lla_lockahead_result);
1176
1177         rc = fstat(fd, &sb);
1178         ASSERTF(!rc, "stat failed for '%s': %s",
1179                 mainpath, strerror(errno));
1180         rc = fstat(fd2, &sb2);
1181         ASSERTF(!rc, "stat failed for '%s': %s",
1182                 mainpath2, strerror(errno));
1183
1184         ASSERTF(sb.st_size == sb2.st_size,
1185                 "size on %s and %s differs: %lu vs %lu",
1186                 mainpath, mainpath2, sb.st_size, sb2.st_size);
1187
1188         ASSERTF(sb.st_size == write_size, "size %lu != bytes written (%lu)",
1189                 sb.st_size, write_size);
1190
1191         close(fd);
1192         close(fd2);
1193
1194         return 0;
1195 }
1196
1197 static void usage(char *prog)
1198 {
1199         fprintf(stderr,
1200                 "Usage: %s [-d lustre_dir], [-D lustre_dir2] [-t test]\n",
1201                 prog);
1202         exit(-1);
1203 }
1204
1205 static void process_args(int argc, char *argv[])
1206 {
1207         int c;
1208
1209         while ((c = getopt(argc, argv, "d:D:f:t:")) != -1) {
1210                 switch (c) {
1211                 case 'f':
1212                         mainfile = optarg;
1213                         break;
1214                 case 'd':
1215                         lustre_dir = optarg;
1216                         break;
1217                 case 'D':
1218                         lustre_dir2 = optarg;
1219                         break;
1220                 case 't':
1221                         single_test = atoi(optarg);
1222                         break;
1223                 case '?':
1224                 default:
1225                         fprintf(stderr, "Invalid option '%c'\n", optopt);
1226                         usage(argv[0]);
1227                         break;
1228                 }
1229         }
1230 }
1231
1232 int main(int argc, char *argv[])
1233 {
1234         char fsname[8];
1235         int rc;
1236
1237         process_args(argc, argv);
1238         if (lustre_dir == NULL)
1239                 lustre_dir = "/mnt/lustre";
1240         if (mainfile == NULL)
1241                 mainfile = "lockahead_test_654";
1242
1243         rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname);
1244         if (rc != 0) {
1245                 fprintf(stderr, "Error: '%s': not a Lustre filesystem\n",
1246                         lustre_dir);
1247                 return -1;
1248         }
1249
1250         if (lustre_dir2) {
1251                 rc = llapi_search_mounts(lustre_dir2, 0, fsmountdir, fsname);
1252                 if (rc != 0) {
1253                         fprintf(stderr,
1254                                 "Error: '%s': not a Lustre filesystem\n",
1255                                 lustre_dir2);
1256                         return -1;
1257                 }
1258         }
1259
1260         /* Play nice with Lustre test scripts. Non-line buffered output
1261          * stream under I/O redirection may appear incorrectly. */
1262         setvbuf(stdout, NULL, _IOLBF, 0);
1263
1264         /* Create a test filename and reuse it. Remove possibly old files. */
1265         rc = snprintf(mainpath, sizeof(mainpath), "%s/%s", lustre_dir,
1266                       mainfile);
1267         ASSERTF(rc > 0 && rc < sizeof(mainpath), "invalid name for mainpath");
1268
1269         if (lustre_dir2) {
1270                 rc = snprintf(mainpath2, sizeof(mainpath2), "%s/%s",
1271                               lustre_dir2, mainfile);
1272                 ASSERTF(rc > 0 && rc < sizeof(mainpath2),
1273                         "invalid name for mainpath2");
1274         }
1275
1276         cleanup();
1277
1278         switch (single_test) {
1279         case 0:
1280                 PERFORM(test10);
1281                 PERFORM(test11);
1282                 PERFORM(test12);
1283                 PERFORM(test13);
1284                 PERFORM(test14);
1285                 PERFORM(test15);
1286                 PERFORM(test16);
1287                 PERFORM(test17);
1288                 PERFORM(test18);
1289                 PERFORM(test19);
1290                 PERFORM(test20);
1291                 PERFORM(test21);
1292                 PERFORM(test22);
1293                 /* Some tests require a second mount point */
1294                 if (lustre_dir2)
1295                         PERFORM(test23);
1296                 /* When running all the test cases, we can't use the return
1297                  * from the last test case, as it might be non-zero to return
1298                  * info, rather than for an error.  Test cases assert and exit
1299                  * if an error occurs. */
1300                 rc = 0;
1301                 break;
1302         case 10:
1303                 PERFORM(test10);
1304                 break;
1305         case 11:
1306                 PERFORM(test11);
1307                 break;
1308         case 12:
1309                 PERFORM(test12);
1310                 break;
1311         case 13:
1312                 PERFORM(test13);
1313                 break;
1314         case 14:
1315                 PERFORM(test14);
1316                 break;
1317         case 15:
1318                 PERFORM(test15);
1319                 break;
1320         case 16:
1321                 PERFORM(test16);
1322                 break;
1323         case 17:
1324                 PERFORM(test17);
1325                 break;
1326         case 18:
1327                 PERFORM(test18);
1328                 break;
1329         case 19:
1330                 PERFORM(test19);
1331                 break;
1332         case 20:
1333                 PERFORM(test20);
1334                 break;
1335         case 21:
1336                 PERFORM(test21);
1337                 break;
1338         case 22:
1339                 PERFORM(test22);
1340                 break;
1341         case 23:
1342                 ASSERTF(lustre_dir2,
1343                         "must provide second mount point for test 23");
1344                 PERFORM(test23);
1345                 break;
1346         default:
1347                 fprintf(stderr, "impossible value of single_test %d\n",
1348                         single_test);
1349                 rc = -1;
1350                 break;
1351         }
1352
1353         return rc;
1354 }