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