Whamcloud - gitweb
LU-9219 tests: add missing mgs reformat to conf-sanity/56
[fs/lustre-release.git] / lustre / tests / llapi_layout_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  * These tests exercise the llapi_layout API which abstracts the layout
24  * of a Lustre file behind an opaque data type.  They assume a Lustre
25  * file system with at least 2 OSTs and a pool containing at least the
26  * first 2 OSTs.  For example,
27  *
28  *  sudo lctl pool_new lustre.testpool
29  *  sudo lctl pool_add lustre.testpool OST[0-1]
30  *  gcc -Wall -g -Werror -o llapi_layout_test llapi_layout_test.c -llustreapi
31  *  sudo ./llapi_layout_test
32  */
33
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <stdint.h>
38 #include <fcntl.h>
39 #include <sys/wait.h>
40 #include <sys/signal.h>
41 #include <sys/types.h>
42 #include <errno.h>
43 #include <lustre/lustreapi.h>
44 #include <pwd.h>
45 #include <limits.h>
46 #include <sys/stat.h>
47 #include <getopt.h>
48 #include <inttypes.h>
49
50 #define ERROR(fmt, ...)                                                 \
51         fprintf(stderr, "%s: %s:%d: %s: " fmt "\n",                     \
52                 program_invocation_short_name, __FILE__, __LINE__,      \
53                 __func__, ## __VA_ARGS__);
54
55 #define DIE(fmt, ...)                   \
56 do {                                    \
57         ERROR(fmt, ## __VA_ARGS__);     \
58         exit(EXIT_FAILURE);             \
59 } while (0)
60
61 #define ASSERTF(cond, fmt, ...)                                         \
62 do {                                                                    \
63         if (!(cond))                                                    \
64                 DIE("assertion '%s' failed: "fmt, #cond, ## __VA_ARGS__);\
65 } while (0)                                                             \
66
67 static char *lustre_dir;
68 static char *poolname;
69 static int num_osts = -1;
70
71 void usage(char *prog)
72 {
73         printf("Usage: %s [-d lustre_dir] [-p pool_name] [-o num_osts] "
74                "[-s $n,$m,..]\n", prog);
75         exit(0);
76 }
77
78 #define T0FILE                  "t0"
79 #define T0_STRIPE_COUNT         num_osts
80 #define T0_STRIPE_SIZE          1048576
81 #define T0_OST_OFFSET           (num_osts - 1)
82 #define T0_DESC         "Read/write layout attributes then create a file"
83 void test0(void)
84 {
85         int rc;
86         int fd;
87         uint64_t count;
88         uint64_t size;
89         struct llapi_layout *layout = llapi_layout_alloc();
90         char path[PATH_MAX];
91         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
92
93         ASSERTF(layout != NULL, "errno %d", errno);
94
95         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
96
97         rc = unlink(path);
98         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
99
100         /* stripe count */
101         rc = llapi_layout_stripe_count_set(layout, T0_STRIPE_COUNT);
102         ASSERTF(rc == 0, "errno = %d", errno);
103         rc = llapi_layout_stripe_count_get(layout, &count);
104         ASSERTF(rc == 0 && count == T0_STRIPE_COUNT, "%"PRIu64" != %d", count,
105                 T0_STRIPE_COUNT);
106
107         /* stripe size */
108         rc = llapi_layout_stripe_size_set(layout, T0_STRIPE_SIZE);
109         ASSERTF(rc == 0, "errno = %d", errno);
110         rc = llapi_layout_stripe_size_get(layout, &size);
111         ASSERTF(rc == 0 && size == T0_STRIPE_SIZE, "%"PRIu64" != %d", size,
112                 T0_STRIPE_SIZE);
113
114         /* pool_name */
115         rc = llapi_layout_pool_name_set(layout, poolname);
116         ASSERTF(rc == 0, "errno = %d", errno);
117         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
118         ASSERTF(rc == 0, "errno = %d", errno);
119         rc = strcmp(mypool, poolname);
120         ASSERTF(rc == 0, "%s != %s", mypool, poolname);
121
122         /* ost_index */
123         rc = llapi_layout_ost_index_set(layout, 0, T0_OST_OFFSET);
124         ASSERTF(rc == 0, "errno = %d", errno);
125
126         /* create */
127         fd = llapi_layout_file_create(path, 0, 0660, layout);
128         ASSERTF(fd >= 0, "path = %s, errno = %d", path, errno);
129         rc = close(fd);
130         ASSERTF(rc == 0, "errno = %d", errno);
131         llapi_layout_free(layout);
132 }
133
134 void __test1_helper(struct llapi_layout *layout)
135 {
136         uint64_t ost0;
137         uint64_t ost1;
138         uint64_t size;
139         uint64_t count;
140         int rc;
141         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
142
143         rc = llapi_layout_stripe_count_get(layout, &count);
144         ASSERTF(count == T0_STRIPE_COUNT, "%"PRIu64" != %d", count,
145                 T0_STRIPE_COUNT);
146
147         rc = llapi_layout_stripe_size_get(layout, &size);
148         ASSERTF(size == T0_STRIPE_SIZE, "%"PRIu64" != %d", size,
149                 T0_STRIPE_SIZE);
150
151         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
152         ASSERTF(rc == 0, "errno = %d", errno);
153         rc = strcmp(mypool, poolname);
154         ASSERTF(rc == 0, "%s != %s", mypool, poolname);
155
156         rc = llapi_layout_ost_index_get(layout, 0, &ost0);
157         ASSERTF(rc == 0, "errno = %d", errno);
158         rc = llapi_layout_ost_index_get(layout, 1, &ost1);
159         ASSERTF(rc == 0, "errno = %d", errno);
160         ASSERTF(ost0 == T0_OST_OFFSET, "%"PRIu64" != %d", ost0, T0_OST_OFFSET);
161         ASSERTF(ost1 != ost0, "%"PRIu64" == %"PRIu64, ost0, ost1);
162 }
163
164 #define T1_DESC         "Read test0 file by path and verify attributes"
165 void test1(void)
166 {
167         char path[PATH_MAX];
168
169         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
170         struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
171         ASSERTF(layout != NULL, "errno = %d", errno);
172         __test1_helper(layout);
173         llapi_layout_free(layout);
174 }
175
176 #define T2_DESC         "Read test0 file by FD and verify attributes"
177 void test2(void)
178 {
179         int fd;
180         int rc;
181         char path[PATH_MAX];
182
183         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
184
185         fd = open(path, O_RDONLY);
186         ASSERTF(fd >= 0, "open(%s): errno = %d", path, errno);
187
188         struct llapi_layout *layout = llapi_layout_get_by_fd(fd, 0);
189         ASSERTF(layout != NULL, "errno = %d", errno);
190
191         rc = close(fd);
192         ASSERTF(rc == 0, "close(%s): errno = %d", path, errno);
193
194         __test1_helper(layout);
195         llapi_layout_free(layout);
196 }
197
198 #define T3_DESC         "Read test0 file by FID and verify attributes"
199 void test3(void)
200 {
201         int rc;
202         struct llapi_layout *layout;
203         lustre_fid fid;
204         char fidstr[4096];
205         char path[PATH_MAX];
206
207         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
208
209         rc = llapi_path2fid(path, &fid);
210         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
211         snprintf(fidstr, sizeof(fidstr), "0x%"PRIx64":0x%x:0x%x",
212                  (uint64_t)fid.f_seq, fid.f_oid, fid.f_ver);
213         errno = 0;
214         layout = llapi_layout_get_by_fid(path, &fid, 0);
215         ASSERTF(layout != NULL, "fidstr = %s, errno = %d", fidstr, errno);
216
217         __test1_helper(layout);
218         llapi_layout_free(layout);
219 }
220
221 #define T4FILE                  "t4"
222 #define T4_STRIPE_COUNT         2
223 #define T4_STRIPE_SIZE          2097152
224 #define T4_DESC         "Verify compatibility with 'lfs setstripe'"
225 void test4(void)
226 {
227         int rc;
228         uint64_t ost0;
229         uint64_t ost1;
230         uint64_t count;
231         uint64_t size;
232         const char *lfs = getenv("LFS");
233         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
234         char cmd[4096];
235         char path[PATH_MAX];
236
237         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T4FILE);
238
239         if (lfs == NULL)
240                 lfs = "/usr/bin/lfs";
241
242         rc = unlink(path);
243         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
244
245         snprintf(cmd, sizeof(cmd), "%s setstripe %s %s -c %d -S %d %s", lfs,
246                  strlen(poolname) > 0 ? "-p" : "", poolname, T4_STRIPE_COUNT,
247                  T4_STRIPE_SIZE, path);
248         rc = system(cmd);
249         ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
250
251         errno = 0;
252         struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
253         ASSERTF(layout != NULL, "errno = %d", errno);
254
255         rc = llapi_layout_stripe_count_get(layout, &count);
256         ASSERTF(count == T4_STRIPE_COUNT, "%"PRIu64" != %d", count,
257                 T4_STRIPE_COUNT);
258
259         rc = llapi_layout_stripe_size_get(layout, &size);
260         ASSERTF(size == T4_STRIPE_SIZE, "%"PRIu64" != %d", size,
261                 T4_STRIPE_SIZE);
262
263         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
264         ASSERTF(rc == 0, "errno = %d", errno);
265         rc = strcmp(mypool, poolname);
266         ASSERTF(rc == 0, "%s != %s", mypool, poolname);
267
268         rc = llapi_layout_ost_index_get(layout, 0, &ost0);
269         ASSERTF(rc == 0, "errno = %d", errno);
270         rc = llapi_layout_ost_index_get(layout, 1, &ost1);
271         ASSERTF(rc == 0, "errno = %d", errno);
272         ASSERTF(ost1 != ost0, "%"PRIu64" == %"PRIu64, ost0, ost1);
273
274         llapi_layout_free(layout);
275 }
276
277 #define T5FILE          "t5"
278 #define T5_DESC         "llapi_layout_get_by_path ENOENT handling"
279 void test5(void)
280 {
281         int rc;
282         char path[PATH_MAX];
283         struct llapi_layout *layout;
284
285         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T5FILE);
286
287         rc = unlink(path);
288         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
289
290         errno = 0;
291         layout = llapi_layout_get_by_path(path, 0);
292         ASSERTF(layout == NULL && errno == ENOENT, "errno = %d", errno);
293 }
294
295 #define T6_DESC         "llapi_layout_get_by_fd EBADF handling"
296 void test6(void)
297 {
298         errno = 0;
299         struct llapi_layout *layout = llapi_layout_get_by_fd(9999, 0);
300         ASSERTF(layout == NULL && errno == EBADF, "errno = %d", errno);
301 }
302
303 #define T7FILE          "t7"
304 #define T7_DESC         "llapi_layout_get_by_path EACCES handling"
305 void test7(void)
306 {
307         int fd;
308         int rc;
309         uid_t myuid = getuid();
310         char path[PATH_MAX];
311         const char *runas = getenv("RUNAS_ID");
312         struct passwd *pw;
313         uid_t uid;
314
315         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T7FILE);
316         ASSERTF(myuid == 0, "myuid = %d", myuid); /* Need root for this test. */
317
318         /* Create file as root */
319         rc = unlink(path);
320         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
321
322         fd = open(path, O_CREAT, 0400);
323         ASSERTF(fd > 0, "errno = %d", errno);
324         rc = close(fd);
325         ASSERTF(rc == 0, "errno = %d", errno);
326
327         /* Become unprivileged user */
328         if (runas != NULL) {
329                 uid = atoi(runas);
330                 ASSERTF(uid != 0, "runas = %s", runas);
331         } else {
332                 pw = getpwnam("nobody");
333                 ASSERTF(pw != NULL, "errno = %d", errno);
334                 uid = pw->pw_uid;
335         }
336         rc = seteuid(uid);
337         ASSERTF(rc == 0, "errno = %d", errno);
338         errno = 0;
339         struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
340         ASSERTF(layout == NULL && errno == EACCES, "errno = %d", errno);
341         rc = seteuid(myuid);
342         ASSERTF(rc == 0, "errno = %d", errno);
343 }
344
345 /* llapi_layout_get_by_path() returns default layout for file with no
346  * striping attributes. */
347 #define T8FILE          "t8"
348 #define T8_DESC         "llapi_layout_get_by_path ENODATA handling"
349 void test8(void)
350 {
351         int fd;
352         int rc;
353         struct llapi_layout *layout;
354         uint64_t count;
355         uint64_t size;
356         uint64_t pattern;
357         char path[PATH_MAX];
358
359         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T8FILE);
360
361         rc = unlink(path);
362         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
363         fd = open(path, O_CREAT, 0640);
364         ASSERTF(fd >= 0, "errno = %d", errno);
365         rc = close(fd);
366         ASSERTF(rc == 0, "errno = %d", errno);
367
368         layout = llapi_layout_get_by_path(path, 0);
369         ASSERTF(layout != NULL, "errno = %d\n", errno);
370
371         rc = llapi_layout_stripe_count_get(layout, &count);
372         ASSERTF(rc == 0, "errno = %d\n", errno);
373         ASSERTF(count == LLAPI_LAYOUT_DEFAULT, "count = %"PRIu64"\n", count);
374
375         rc = llapi_layout_stripe_size_get(layout, &size);
376         ASSERTF(rc == 0, "errno = %d\n", errno);
377         ASSERTF(size == LLAPI_LAYOUT_DEFAULT, "size = %"PRIu64"\n", size);
378
379         rc = llapi_layout_pattern_get(layout, &pattern);
380         ASSERTF(rc == 0, "errno = %d\n", errno);
381         ASSERTF(pattern == LLAPI_LAYOUT_DEFAULT, "pattern = %"PRIu64"\n",
382                 pattern);
383
384         llapi_layout_free(layout);
385 }
386
387 /* Verify llapi_layout_patter_set() return values for various inputs. */
388 #define T9_DESC         "verify llapi_layout_pattern_set() return values"
389 void test9(void)
390 {
391         struct llapi_layout *layout;
392         int rc;
393
394         layout = llapi_layout_alloc();
395         ASSERTF(layout != NULL, "errno = %d\n", errno);
396
397         errno = 0;
398         rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_INVALID);
399         ASSERTF(rc == -1 && errno == EOPNOTSUPP, "rc = %d, errno = %d", rc,
400                 errno);
401
402         errno = 0;
403         rc = llapi_layout_pattern_set(NULL, LLAPI_LAYOUT_DEFAULT);
404         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc,
405                 errno);
406
407         errno = 0;
408         rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_DEFAULT);
409         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
410
411         errno = 0;
412         rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_RAID0);
413         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
414
415         llapi_layout_free(layout);
416 }
417
418 /* Verify stripe_count interfaces return errors as expected */
419 #define T10_DESC        "stripe_count error handling"
420 void test10(void)
421 {
422         int rc;
423         uint64_t count;
424         struct llapi_layout *layout;
425
426         layout = llapi_layout_alloc();
427         ASSERTF(layout != NULL, "errno = %d", errno);
428
429         /* invalid stripe count */
430         errno = 0;
431         rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_INVALID);
432         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
433
434         errno = 0;
435         rc = llapi_layout_stripe_count_set(layout, -1);
436         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
437
438         /* NULL layout */
439         errno = 0;
440         rc = llapi_layout_stripe_count_set(NULL, 2);
441         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
442
443         /* NULL layout */
444         errno = 0;
445         rc = llapi_layout_stripe_count_get(NULL, &count);
446         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
447
448         /* NULL count */
449         errno = 0;
450         rc = llapi_layout_stripe_count_get(layout, NULL);
451         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
452
453         /* stripe count too large */
454         errno = 0;
455         rc = llapi_layout_stripe_count_set(layout, LOV_MAX_STRIPE_COUNT + 1);
456         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
457         llapi_layout_free(layout);
458 }
459
460 /* Verify stripe_size interfaces return errors as expected */
461 #define T11_DESC        "stripe_size error handling"
462 void test11(void)
463 {
464         int rc;
465         uint64_t size;
466         struct llapi_layout *layout;
467
468         layout = llapi_layout_alloc();
469         ASSERTF(layout != NULL, "errno = %d", errno);
470
471         /* negative stripe size */
472         errno = 0;
473         rc = llapi_layout_stripe_size_set(layout, -1);
474         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
475
476         /* invalid stripe size */
477         errno = 0;
478         rc = llapi_layout_stripe_size_set(layout, LLAPI_LAYOUT_INVALID);
479         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
480
481         /* stripe size too big */
482         errno = 0;
483         rc = llapi_layout_stripe_size_set(layout, (1ULL << 33));
484         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
485
486         /* NULL layout */
487         errno = 0;
488         rc = llapi_layout_stripe_size_set(NULL, 1048576);
489         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
490
491         errno = 0;
492         rc = llapi_layout_stripe_size_get(NULL, &size);
493         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
494
495         /* NULL size */
496         errno = 0;
497         rc = llapi_layout_stripe_size_get(layout, NULL);
498         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
499
500         llapi_layout_free(layout);
501 }
502
503 /* Verify pool_name interfaces return errors as expected */
504 #define T12_DESC        "pool_name error handling"
505 void test12(void)
506 {
507         int rc;
508         struct llapi_layout *layout;
509         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
510
511         layout = llapi_layout_alloc();
512         ASSERTF(layout != NULL, "errno = %d", errno);
513
514         /* NULL layout */
515         errno = 0;
516         rc = llapi_layout_pool_name_set(NULL, "foo");
517         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
518
519         /* NULL pool name */
520         errno = 0;
521         rc = llapi_layout_pool_name_set(layout, NULL);
522         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
523
524         /* NULL layout */
525         errno = 0;
526         rc = llapi_layout_pool_name_get(NULL, mypool, sizeof(mypool));
527         ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
528
529         /* NULL buffer */
530         errno = 0;
531         rc = llapi_layout_pool_name_get(layout, NULL, sizeof(mypool));
532         ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
533
534         /* Pool name too long*/
535         errno = 0;
536         rc = llapi_layout_pool_name_set(layout, "0123456789abcdef");
537         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
538
539         llapi_layout_free(layout);
540 }
541
542 /* Verify ost_index interface returns errors as expected */
543 #define T13FILE                 "t13"
544 #define T13_STRIPE_COUNT        2
545 #define T13_DESC                "ost_index error handling"
546 void test13(void)
547 {
548         int rc;
549         int fd;
550         uint64_t idx;
551         struct llapi_layout *layout;
552         char path[PATH_MAX];
553
554         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T13FILE);
555
556         layout = llapi_layout_alloc();
557         ASSERTF(layout != NULL, "errno = %d", errno);
558
559         /* invalid OST index */
560         errno = 0;
561         rc = llapi_layout_ost_index_set(layout, 0, LLAPI_LAYOUT_INVALID);
562         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
563
564         errno = 0;
565         rc = llapi_layout_ost_index_set(layout, 0, -1);
566         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
567
568         /* NULL layout */
569         errno = 0;
570         rc = llapi_layout_ost_index_set(NULL, 0, 1);
571         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
572
573         errno = 0;
574         rc = llapi_layout_ost_index_get(NULL, 0, &idx);
575         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
576
577         /* NULL index */
578         errno = 0;
579         rc = llapi_layout_ost_index_get(layout, 0, NULL);
580         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
581
582         /* Layout not read from file so has no OST data. */
583         errno = 0;
584         rc = llapi_layout_stripe_count_set(layout, T13_STRIPE_COUNT);
585         ASSERTF(rc == 0, "errno = %d", errno);
586         rc = llapi_layout_ost_index_get(layout, 0, &idx);
587         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
588
589         /* n greater than stripe count*/
590         rc = unlink(path);
591         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
592         rc = llapi_layout_stripe_count_set(layout, T13_STRIPE_COUNT);
593         ASSERTF(rc == 0, "errno = %d", errno);
594         fd = llapi_layout_file_create(path, 0, 0644, layout);
595         ASSERTF(fd >= 0, "errno = %d", errno);
596         rc = close(fd);
597         ASSERTF(rc == 0, "errno = %d", errno);
598         llapi_layout_free(layout);
599
600         layout = llapi_layout_get_by_path(path, 0);
601         ASSERTF(layout != NULL, "errno = %d", errno);
602         errno = 0;
603         rc = llapi_layout_ost_index_get(layout, T13_STRIPE_COUNT + 1, &idx);
604         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
605
606         llapi_layout_free(layout);
607 }
608
609 /* Verify llapi_layout_file_create() returns errors as expected */
610 #define T14_DESC        "llapi_layout_file_create error handling"
611 void test14(void)
612 {
613         int rc;
614         struct llapi_layout *layout = llapi_layout_alloc();
615
616         /* NULL path */
617         errno = 0;
618         rc = llapi_layout_file_create(NULL, 0, 0, layout);
619         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
620
621         llapi_layout_free(layout);
622 }
623
624 /* Can't change striping attributes of existing file. */
625 #define T15FILE                 "t15"
626 #define T15_STRIPE_COUNT        2
627 #define T15_DESC        "Can't change striping attributes of existing file"
628 void test15(void)
629 {
630         int rc;
631         int fd;
632         uint64_t count;
633         struct llapi_layout *layout;
634         char path[PATH_MAX];
635
636         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T15FILE);
637
638         rc = unlink(path);
639         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
640
641         layout = llapi_layout_alloc();
642         ASSERTF(layout != NULL, "errno = %d", errno);
643         rc = llapi_layout_stripe_count_set(layout, T15_STRIPE_COUNT);
644         ASSERTF(rc == 0, "errno = %d", errno);
645
646         errno = 0;
647         fd = llapi_layout_file_create(path, 0, 0640, layout);
648         ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
649         rc = close(fd);
650         ASSERTF(rc == 0, "errno = %d", errno);
651
652         rc = llapi_layout_stripe_count_set(layout, T15_STRIPE_COUNT - 1);
653         errno = 0;
654         fd = llapi_layout_file_open(path, 0, 0640, layout);
655         ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
656         rc = close(fd);
657         ASSERTF(rc == 0, "errno = %d", errno);
658         llapi_layout_free(layout);
659
660         layout = llapi_layout_get_by_path(path, 0);
661         ASSERTF(layout != NULL, "errno = %d", errno);
662         rc = llapi_layout_stripe_count_get(layout, &count);
663         ASSERTF(rc == 0 && count == T15_STRIPE_COUNT,
664                 "rc = %d, %"PRIu64" != %d", rc, count, T15_STRIPE_COUNT);
665         llapi_layout_free(layout);
666 }
667
668 /* Default stripe attributes are applied as expected. */
669 #define T16FILE         "t16"
670 #define T16_DESC        "Default stripe attributes are applied as expected"
671 void test16(void)
672 {
673         int             rc;
674         int             fd;
675         struct llapi_layout     *deflayout;
676         struct llapi_layout     *filelayout;
677         char            path[PATH_MAX];
678         uint64_t        fsize;
679         uint64_t        fcount;
680         uint64_t        dsize;
681         uint64_t        dcount;
682
683         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T16FILE);
684
685         rc = unlink(path);
686         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
687
688         deflayout = llapi_layout_get_by_path(lustre_dir, LAYOUT_GET_EXPECTED);
689         ASSERTF(deflayout != NULL, "errno = %d", errno);
690         rc = llapi_layout_stripe_size_get(deflayout, &dsize);
691         ASSERTF(rc == 0, "errno = %d", errno);
692         rc = llapi_layout_stripe_count_get(deflayout, &dcount);
693         ASSERTF(rc == 0, "errno = %d", errno);
694
695         /* First, with a default struct llapi_layout */
696         filelayout = llapi_layout_alloc();
697         ASSERTF(filelayout != NULL, "errno = %d", errno);
698
699         fd = llapi_layout_file_create(path, 0, 0640, filelayout);
700         ASSERTF(fd >= 0, "errno = %d", errno);
701
702         rc = close(fd);
703         ASSERTF(rc == 0, "errno = %d", errno);
704
705         llapi_layout_free(filelayout);
706
707         filelayout = llapi_layout_get_by_path(path, 0);
708         ASSERTF(filelayout != NULL, "errno = %d", errno);
709
710         rc = llapi_layout_stripe_count_get(filelayout, &fcount);
711         ASSERTF(rc == 0, "errno = %d", errno);
712         ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
713                 dcount == LLAPI_LAYOUT_WIDE,
714                 "%"PRIu64" != %"PRIu64, fcount, dcount);
715
716         rc = llapi_layout_stripe_size_get(filelayout, &fsize);
717         ASSERTF(rc == 0, "errno = %d", errno);
718         ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
719
720         /* NULL layout also implies default layout */
721         rc = unlink(path);
722         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
723
724         fd = llapi_layout_file_create(path, 0, 0640, filelayout);
725         ASSERTF(fd >= 0, "errno = %d", errno);
726         rc = close(fd);
727         ASSERTF(rc == 0, "errno = %d", errno);
728         filelayout = llapi_layout_get_by_path(path, 0);
729         ASSERTF(filelayout != NULL, "errno = %d", errno);
730
731         rc = llapi_layout_stripe_count_get(filelayout, &fcount);
732         ASSERTF(rc == 0, "errno = %d", errno);
733         rc = llapi_layout_stripe_size_get(filelayout, &fsize);
734         ASSERTF(rc == 0, "errno = %d", errno);
735         ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
736                 dcount == LLAPI_LAYOUT_WIDE,
737                 "%"PRIu64" != %"PRIu64, fcount, dcount);
738         ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
739
740         llapi_layout_free(filelayout);
741         llapi_layout_free(deflayout);
742 }
743
744 /* Setting stripe count to LLAPI_LAYOUT_WIDE uses all available OSTs. */
745 #define T17FILE         "t17"
746 #define T17_DESC        "LLAPI_LAYOUT_WIDE is honored"
747 void test17(void)
748 {
749         int rc;
750         int fd;
751         int osts_all;
752         uint64_t osts_layout;
753         struct llapi_layout *layout;
754         char path[PATH_MAX];
755
756         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T17FILE);
757
758         rc = unlink(path);
759         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
760         layout = llapi_layout_alloc();
761         ASSERTF(layout != NULL, "errno = %d", errno);
762         rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_WIDE);
763         ASSERTF(rc == 0, "errno = %d", errno);
764         fd = llapi_layout_file_create(path, 0, 0640, layout);
765         ASSERTF(fd >= 0, "errno = %d", errno);
766         rc = close(fd);
767         ASSERTF(rc == 0, "errno = %d", errno);
768         llapi_layout_free(layout);
769
770         /* Get number of available OSTs */
771         fd = open(path, O_RDONLY);
772         ASSERTF(fd >= 0, "errno = %d", errno);
773         rc = llapi_lov_get_uuids(fd, NULL, &osts_all);
774         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
775         rc = close(fd);
776         ASSERTF(rc == 0, "errno = %d", errno);
777
778         layout = llapi_layout_get_by_path(path, 0);
779         ASSERTF(layout != NULL, "errno = %d", errno);
780         rc = llapi_layout_stripe_count_get(layout, &osts_layout);
781         ASSERTF(osts_layout == osts_all, "%"PRIu64" != %d", osts_layout,
782                 osts_all);
783
784         llapi_layout_free(layout);
785 }
786
787 /* Setting pool with "fsname.pool" notation. */
788 #define T18FILE         "t18"
789 #define T18_DESC        "Setting pool with fsname.pool notation"
790 void test18(void)
791 {
792         int rc;
793         int fd;
794         struct llapi_layout *layout = llapi_layout_alloc();
795         char path[PATH_MAX];
796         char pool[LOV_MAXPOOLNAME*2 + 1];
797         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
798
799         snprintf(pool, sizeof(pool), "lustre.%s", poolname);
800
801         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T18FILE);
802
803         ASSERTF(layout != NULL, "errno = %d", errno);
804
805         rc = unlink(path);
806         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
807
808         rc = llapi_layout_pool_name_set(layout, pool);
809         ASSERTF(rc == 0, "errno = %d", errno);
810
811         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
812         ASSERTF(rc == 0, "errno = %d", errno);
813         rc = strcmp(mypool, poolname);
814         ASSERTF(rc == 0, "%s != %s", mypool, poolname);
815         fd = llapi_layout_file_create(path, 0, 0640, layout);
816         ASSERTF(fd >= 0, "errno = %d", errno);
817         rc = close(fd);
818         ASSERTF(rc == 0, "errno = %d", errno);
819
820         llapi_layout_free(layout);
821
822         layout = llapi_layout_get_by_path(path, 0);
823         ASSERTF(layout != NULL, "errno = %d", errno);
824         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
825         ASSERTF(rc == 0, "errno = %d", errno);
826         rc = strcmp(mypool, poolname);
827         ASSERTF(rc == 0, "%s != %s", mypool, poolname);
828         llapi_layout_free(layout);
829 }
830
831 #define T19_DESC        "Maximum length pool name is NULL-terminated"
832 void test19(void)
833 {
834         struct llapi_layout *layout;
835         char *name = "0123456789abcde";
836         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
837         int rc;
838
839         layout = llapi_layout_alloc();
840         ASSERTF(layout != NULL, "errno = %d", errno);
841         rc = llapi_layout_pool_name_set(layout, name);
842         ASSERTF(rc == 0, "errno = %d", errno);
843         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
844         ASSERTF(strlen(name) == strlen(mypool), "name = %s, str = %s", name,
845                 mypool);
846         llapi_layout_free(layout);
847 }
848
849 #define T20FILE         "t20"
850 #define T20_DESC        "LLAPI_LAYOUT_DEFAULT is honored"
851 void test20(void)
852 {
853         int             rc;
854         int             fd;
855         struct llapi_layout     *deflayout;
856         struct llapi_layout     *filelayout;
857         char            path[PATH_MAX];
858         uint64_t        fsize;
859         uint64_t        fcount;
860         uint64_t        dsize;
861         uint64_t        dcount;
862
863         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T20FILE);
864
865         rc = unlink(path);
866         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
867
868         filelayout = llapi_layout_alloc();
869         ASSERTF(filelayout != NULL, "errno = %d", errno);
870
871         rc = llapi_layout_stripe_size_set(filelayout, LLAPI_LAYOUT_DEFAULT);
872         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
873
874         rc = llapi_layout_stripe_count_set(filelayout, LLAPI_LAYOUT_DEFAULT);
875         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
876
877         fd = llapi_layout_file_create(path, 0, 0640, filelayout);
878         ASSERTF(fd >= 0, "errno = %d", errno);
879
880         rc = close(fd);
881         ASSERTF(rc == 0, "errno = %d", errno);
882
883         llapi_layout_free(filelayout);
884
885         deflayout = llapi_layout_get_by_path(lustre_dir, LAYOUT_GET_EXPECTED);
886         ASSERTF(deflayout != NULL, "errno = %d", errno);
887
888         filelayout = llapi_layout_get_by_path(path, 0);
889         ASSERTF(filelayout != NULL, "errno = %d", errno);
890
891         rc = llapi_layout_stripe_count_get(filelayout, &fcount);
892         ASSERTF(rc == 0, "errno = %d", errno);
893         rc = llapi_layout_stripe_count_get(deflayout, &dcount);
894         ASSERTF(rc == 0, "errno = %d", errno);
895         ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
896                 dcount == LLAPI_LAYOUT_WIDE,
897                 "%"PRIu64" != %"PRIu64, fcount, dcount);
898
899         rc = llapi_layout_stripe_size_get(filelayout, &fsize);
900         ASSERTF(rc == 0, "errno = %d", errno);
901         rc = llapi_layout_stripe_size_get(deflayout, &dsize);
902         ASSERTF(rc == 0, "errno = %d", errno);
903         ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
904
905         llapi_layout_free(filelayout);
906         llapi_layout_free(deflayout);
907 }
908
909 #define T21_DESC        "llapi_layout_file_create fails for non-Lustre file"
910 void test21(void)
911 {
912         struct llapi_layout *layout;
913         char template[PATH_MAX];
914         int fd;
915         int rc;
916
917         snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
918         fd = mkstemp(template);
919         ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
920         rc = close(fd);
921         ASSERTF(rc == 0, "errno = %d", fd);
922         rc = unlink(template);
923         ASSERTF(rc == 0, "errno = %d", errno);
924
925         layout = llapi_layout_alloc();
926         ASSERTF(layout != NULL, "errno = %d", errno);
927
928         fd = llapi_layout_file_create(template, 0, 0640, layout);
929         ASSERTF(fd == -1 && errno == ENOTTY,
930                 "fd = %d, errno = %d, template = %s", fd, errno, template);
931         llapi_layout_free(layout);
932 }
933
934 #define T22FILE         "t22"
935 #define T22_DESC        "llapi_layout_file_create applied mode correctly"
936 void test22(void)
937 {
938         int             rc;
939         int             fd;
940         char            path[PATH_MAX];
941         struct stat     st;
942         mode_t          mode_in = 0640;
943         mode_t          mode_out;
944         mode_t          umask_orig;
945
946         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T22FILE);
947
948         rc = unlink(path);
949         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
950
951         umask_orig = umask(S_IWGRP | S_IWOTH);
952
953         fd = llapi_layout_file_create(path, 0, mode_in, NULL);
954         ASSERTF(fd >= 0, "errno = %d", errno);
955
956         (void) umask(umask_orig);
957
958         rc = fstat(fd, &st);
959         ASSERTF(rc == 0, "errno = %d", errno);
960
961         rc = close(fd);
962         ASSERTF(rc == 0, "errno = %d", fd);
963
964         mode_out = st.st_mode & ~S_IFMT;
965         ASSERTF(mode_in == mode_out, "%o != %o", mode_in, mode_out);
966 }
967
968 #define T23_DESC        "llapi_layout_get_by_path fails for non-Lustre file"
969 void test23(void)
970 {
971         struct llapi_layout *layout;
972         char template[PATH_MAX];
973         int fd;
974         int rc;
975
976         snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
977         fd = mkstemp(template);
978         ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
979         rc = close(fd);
980         ASSERTF(rc == 0, "errno = %d", fd);
981
982         layout = llapi_layout_get_by_path(template, 0);
983         ASSERTF(layout == NULL && errno == ENOTTY,
984                 "errno = %d, template = %s", errno, template);
985
986         rc = unlink(template);
987         ASSERTF(rc == 0, "errno = %d", errno);
988 }
989
990 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
991  * for file with unspecified layout. */
992 #define T24FILE         "t24"
993 #define T24_DESC        "LAYOUT_GET_EXPECTED works with existing file"
994 void test24(void)
995 {
996         int fd;
997         int rc;
998         struct llapi_layout *layout;
999         uint64_t count;
1000         uint64_t size;
1001         uint64_t pattern;
1002         char path[PATH_MAX];
1003
1004         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T24FILE);
1005
1006         rc = unlink(path);
1007         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1008         fd = open(path, O_CREAT, 0640);
1009         ASSERTF(fd >= 0, "errno = %d", errno);
1010         rc = close(fd);
1011         ASSERTF(rc == 0, "errno = %d", errno);
1012
1013         layout = llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED);
1014         ASSERTF(layout != NULL, "errno = %d\n", errno);
1015
1016         rc = llapi_layout_stripe_count_get(layout, &count);
1017         ASSERTF(rc == 0, "errno = %d\n", errno);
1018         ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1019
1020         rc = llapi_layout_stripe_size_get(layout, &size);
1021         ASSERTF(rc == 0, "errno = %d\n", errno);
1022         ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1023
1024         rc = llapi_layout_pattern_get(layout, &pattern);
1025         ASSERTF(rc == 0, "errno = %d\n", errno);
1026         ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1027
1028         llapi_layout_free(layout);
1029 }
1030
1031 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
1032  * for directory with unspecified layout. */
1033 #define T25DIR          "d25"
1034 #define T25_DESC        "LAYOUT_GET_EXPECTED works with directory"
1035 void test25(void)
1036 {
1037         int rc;
1038         struct llapi_layout *layout;
1039         uint64_t count;
1040         uint64_t size;
1041         uint64_t pattern;
1042         char dir[PATH_MAX];
1043
1044         snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T25DIR);
1045
1046         rc = rmdir(dir);
1047         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1048         rc = mkdir(dir, 0750);
1049         ASSERTF(rc == 0, "errno = %d", errno);
1050
1051         layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1052         ASSERTF(layout != NULL, "errno = %d\n", errno);
1053
1054         rc = llapi_layout_stripe_count_get(layout, &count);
1055         ASSERTF(rc == 0, "errno = %d\n", errno);
1056         ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1057
1058         rc = llapi_layout_stripe_size_get(layout, &size);
1059         ASSERTF(rc == 0, "errno = %d\n", errno);
1060         ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1061
1062         rc = llapi_layout_pattern_get(layout, &pattern);
1063         ASSERTF(rc == 0, "errno = %d\n", errno);
1064         ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1065
1066         llapi_layout_free(layout);
1067 }
1068
1069 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) correctly combines
1070  * specified attributes of parent directory with attributes filesystem root. */
1071 #define T26DIR          "d26"
1072 #define T26_DESC        "LAYOUT_GET_EXPECTED partially specified parent"
1073 #define T26_STRIPE_SIZE (1048576 * 4)
1074 void test26(void)
1075 {
1076         int rc;
1077         struct llapi_layout *layout;
1078         const char *lfs = getenv("LFS");
1079         uint64_t count;
1080         uint64_t size;
1081         uint64_t pattern;
1082         char dir[PATH_MAX];
1083         char cmd[4096];
1084
1085         snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T26DIR);
1086         rc = rmdir(dir);
1087         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1088         rc = mkdir(dir, 0750);
1089         ASSERTF(rc == 0, "errno = %d", errno);
1090
1091         if (lfs == NULL)
1092                 lfs = "/usr/bin/lfs";
1093
1094         snprintf(cmd, sizeof(cmd), "%s setstripe -S %d %s", lfs,
1095                  T26_STRIPE_SIZE, dir);
1096         rc = system(cmd);
1097         ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1098
1099         layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1100         ASSERTF(layout != NULL, "errno = %d\n", errno);
1101
1102         rc = llapi_layout_stripe_count_get(layout, &count);
1103         ASSERTF(rc == 0, "errno = %d\n", errno);
1104         ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1105
1106         rc = llapi_layout_stripe_size_get(layout, &size);
1107         ASSERTF(rc == 0, "errno = %d\n", errno);
1108         ASSERTF(size == T26_STRIPE_SIZE, "size = %"PRIu64, size);
1109
1110         rc = llapi_layout_pattern_get(layout, &pattern);
1111         ASSERTF(rc == 0, "errno = %d\n", errno);
1112         ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1113
1114         llapi_layout_free(layout);
1115 }
1116
1117 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) work with
1118  * non existing file. */
1119 #define T27DIR          "d27"
1120 #define T27_DESC        "LAYOUT_GET_EXPECTED with non existing file"
1121 #define T27_STRIPE_SIZE (1048576 * 3)
1122 void test27(void)
1123 {
1124         int rc;
1125         struct llapi_layout *layout;
1126         const char *lfs = getenv("LFS");
1127         uint64_t count;
1128         uint64_t size;
1129         uint64_t pattern;
1130         char dirpath[PATH_MAX];
1131         char filepath[PATH_MAX];
1132         char cmd[4096];
1133
1134         snprintf(dirpath, sizeof(dirpath), "%s/%s", lustre_dir, T27DIR);
1135         snprintf(filepath, sizeof(filepath), "%s/nonesuch", dirpath);
1136
1137         rc = rmdir(dirpath);
1138         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1139         rc = mkdir(dirpath, 0750);
1140         ASSERTF(rc == 0, "errno = %d", errno);
1141
1142         if (lfs == NULL)
1143                 lfs = "/usr/bin/lfs";
1144
1145         snprintf(cmd, sizeof(cmd), "%s setstripe -S %d %s", lfs,
1146                  T27_STRIPE_SIZE, dirpath);
1147         rc = system(cmd);
1148         ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1149
1150         layout = llapi_layout_get_by_path(filepath, LAYOUT_GET_EXPECTED);
1151         ASSERTF(layout != NULL, "errno = %d\n", errno);
1152
1153         rc = llapi_layout_stripe_count_get(layout, &count);
1154         ASSERTF(rc == 0, "errno = %d\n", errno);
1155         ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1156
1157         rc = llapi_layout_stripe_size_get(layout, &size);
1158         ASSERTF(rc == 0, "errno = %d\n", errno);
1159         ASSERTF(size == T27_STRIPE_SIZE, "size = %"PRIu64, size);
1160
1161         rc = llapi_layout_pattern_get(layout, &pattern);
1162         ASSERTF(rc == 0, "errno = %d\n", errno);
1163         ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1164
1165         llapi_layout_free(layout);
1166 }
1167
1168 /* llapi_layout_stripe_count_get returns LLAPI_LAYOUT_WIDE for a directory
1169  * with a stripe_count of -1. */
1170 #define T28DIR          "d28"
1171 #define T28_DESC        "LLAPI_LAYOUT_WIDE returned as expected"
1172 void test28(void)
1173 {
1174         int rc;
1175         struct llapi_layout *layout;
1176         const char *lfs = getenv("LFS");
1177         uint64_t count;
1178         char dirpath[PATH_MAX];
1179         char cmd[4096];
1180
1181         snprintf(dirpath, sizeof(dirpath), "%s/%s", lustre_dir, T28DIR);
1182
1183         rc = rmdir(dirpath);
1184         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1185         rc = mkdir(dirpath, 0750);
1186         ASSERTF(rc == 0, "errno = %d", errno);
1187
1188         if (lfs == NULL)
1189                 lfs = "/usr/bin/lfs";
1190
1191         snprintf(cmd, sizeof(cmd), "%s setstripe -c -1 %s", lfs, dirpath);
1192         rc = system(cmd);
1193         ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1194
1195         layout = llapi_layout_get_by_path(dirpath, 0);
1196         ASSERTF(layout != NULL, "errno = %d\n", errno);
1197
1198         rc = llapi_layout_stripe_count_get(layout, &count);
1199         ASSERTF(rc == 0, "errno = %d\n", errno);
1200         ASSERTF(count == LLAPI_LAYOUT_WIDE, "count = %"PRIu64"\n", count);
1201
1202         llapi_layout_free(layout);
1203 }
1204
1205 #define T29FILE         "f29"
1206 #define T29_DESC        "set ost index to non-zero stripe number"
1207 void test29(void)
1208 {
1209         int rc, fd, i;
1210         uint64_t ost0, ost1, nost;
1211         struct llapi_layout *layout;
1212         char path[PATH_MAX];
1213
1214         if (num_osts < 2)
1215                 return;
1216
1217         layout = llapi_layout_alloc();
1218         ASSERTF(layout != NULL, "errno %d", errno);
1219
1220         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T29FILE);
1221
1222         rc = unlink(path);
1223         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1224
1225         /* set ost index to LLAPI_LAYOUT_IDX_MAX should fail */
1226         rc = llapi_layout_ost_index_set(layout, 1, LLAPI_LAYOUT_IDX_MAX);
1227         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d\n",
1228                 rc, errno);
1229
1230         /* specify ost index partially */
1231         rc = llapi_layout_ost_index_set(layout, 1, 0);
1232         ASSERTF(rc == 0, "errno = %d", errno);
1233
1234         /* create a partially specified layout will fail */
1235         fd = llapi_layout_file_create(path, 0, 0660, layout);
1236         ASSERTF(fd == -1 && errno == EINVAL, "path = %s, fd = %d, errno = %d",
1237                 path, fd, errno);
1238
1239         rc = unlink(path);
1240         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1241
1242         /* specify all stripes */
1243         rc = llapi_layout_ost_index_set(layout, 0, 1);
1244         ASSERTF(rc == 0, "errno = %d", errno);
1245
1246         /* create */
1247         fd = llapi_layout_file_create(path, 0, 0660, layout);
1248         ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1249
1250         rc = close(fd);
1251         ASSERTF(rc == 0, "errno = %d", errno);
1252         llapi_layout_free(layout);
1253
1254         /* get layout from file */
1255         layout = llapi_layout_get_by_path(path, 0);
1256         ASSERTF(layout != NULL, "errno = %d", errno);
1257
1258         rc = llapi_layout_ost_index_get(layout, 0, &ost0);
1259         ASSERTF(rc == 0, "errno = %d", errno);
1260         rc = llapi_layout_ost_index_get(layout, 1, &ost1);
1261         ASSERTF(rc == 0, "errno = %d", errno);
1262         ASSERTF(ost0 == 1, "%"PRIu64" != %d", ost0, 1);
1263         ASSERTF(ost1 == 0, "%"PRIu64" != %d", ost1, 0);
1264         llapi_layout_free(layout);
1265
1266         /* specify more ost indexes to test realloc */
1267         nost = 0;
1268         layout = llapi_layout_alloc();
1269         ASSERTF(layout != NULL, "errno %d", errno);
1270         for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++) {
1271                 rc = llapi_layout_ost_index_set(layout, i, nost);
1272                 ASSERTF(rc == 0, "errno = %d", errno);
1273                 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1274                 ASSERTF(rc == 0, "errno = %d", errno);
1275                 nost++;
1276                 if (nost == num_osts)
1277                         nost = 0;
1278         }
1279
1280         nost = 0;
1281         for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++) {
1282                 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1283                 ASSERTF(rc == 0, "errno = %d", errno);
1284                 ASSERTF(ost0 == nost, "ost=%"PRIu64" nost=%"PRIu64"",
1285                         ost0, nost);
1286                 nost++;
1287                 if (nost == num_osts)
1288                         nost = 0;
1289         }
1290         llapi_layout_free(layout);
1291
1292         nost = 0;
1293         layout = llapi_layout_alloc();
1294         ASSERTF(layout != NULL, "errno %d", errno);
1295         for (i = LOV_MAX_STRIPE_COUNT-1; i >= 0; i--) {
1296                 rc = llapi_layout_ost_index_set(layout, i, nost);
1297                 ASSERTF(rc == 0, "errno = %d", errno);
1298                 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1299                 ASSERTF(rc == 0, "errno = %d", errno);
1300                 nost++;
1301                 if (nost == num_osts)
1302                         nost = 0;
1303         }
1304
1305         nost = 0;
1306         for (i = LOV_MAX_STRIPE_COUNT-1; i <= 0; i--) {
1307                 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1308                 ASSERTF(rc == 0, "errno = %d", errno);
1309                 ASSERTF(ost0 == nost, "ost=%"PRIu64", nost=%"PRIu64"",
1310                         ost0, nost);
1311                 nost++;
1312                 if (nost == num_osts)
1313                         nost = 0;
1314         }
1315         llapi_layout_free(layout);
1316 }
1317
1318 #define T30FILE         "f30"
1319 #define T30_DESC        "create composite file, traverse components"
1320 void test30(void)
1321 {
1322         int rc, fd;
1323         uint64_t start[3], end[3];
1324         uint64_t s, e;
1325         struct llapi_layout *layout;
1326         char path[PATH_MAX];
1327
1328         start[0] = 0;
1329         end[0] = 64 * 1024 * 1024; /* 64m */
1330         start[1] = end[0];
1331         end[1] = 1 * 1024 * 1024 * 1024; /* 1G */
1332         start[2] = end[1];
1333         end[2] = LUSTRE_EOF;
1334
1335         if (num_osts < 2)
1336                 return;
1337
1338         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T30FILE);
1339
1340         rc = unlink(path);
1341         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1342
1343         layout = llapi_layout_alloc();
1344         ASSERTF(layout != NULL, "errno %d", errno);
1345
1346         rc = llapi_layout_stripe_count_set(layout, 1);
1347         ASSERTF(rc == 0, "errno %d", errno);
1348
1349         /* add component without adjusting previous component's extent
1350          * end will fail. */
1351         rc = llapi_layout_comp_add(layout);
1352         ASSERTF(rc == -1 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1353
1354         rc = llapi_layout_comp_extent_set(layout, start[0], end[0]);
1355         ASSERTF(rc == 0, "errno %d", errno);
1356
1357         rc = llapi_layout_comp_add(layout);
1358         ASSERTF(rc == 0, "errno %d", errno);
1359
1360         /* set non-contiguous extent will fail */
1361         rc = llapi_layout_comp_extent_set(layout, end[0] * 2, end[1]);
1362         ASSERTF(rc == -1 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1363
1364         rc = llapi_layout_comp_extent_set(layout, start[1], end[1]);
1365         ASSERTF(rc == 0, "errno %d", errno);
1366
1367         rc = llapi_layout_comp_add(layout);
1368         ASSERTF(rc == 0, "errno %d", errno);
1369
1370         rc = llapi_layout_comp_extent_set(layout, start[2], end[2]);
1371         ASSERTF(rc == 0, "errno %d", errno);
1372
1373         /* create composite file */
1374         fd = llapi_layout_file_create(path, 0, 0660, layout);
1375         ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1376
1377         llapi_layout_free(layout);
1378
1379         /* traverse & verify all components */
1380         layout = llapi_layout_get_by_path(path, 0);
1381         ASSERTF(layout != NULL, "errno = %d", errno);
1382
1383         /* current component should be the tail component */
1384         rc = llapi_layout_comp_extent_get(layout, &s, &e);
1385         ASSERTF(rc == 0, "errno %d", errno);
1386         ASSERTF(s == start[2] && e == end[2],
1387                 "s: %"PRIu64", e: %"PRIu64"", s, e);
1388
1389         rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1390         ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1391
1392         /* delete non-tail component will fail */
1393         rc = llapi_layout_comp_del(layout);
1394         ASSERTF(rc == -1 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1395
1396         rc = llapi_layout_comp_extent_get(layout, &s, &e);
1397         ASSERTF(rc == 0, "errno %d", errno);
1398         ASSERTF(s == start[0] && e == end[0],
1399                 "s: %"PRIu64", e: %"PRIu64"", s, e);
1400
1401         rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
1402         ASSERTF(rc == 0, "rc %d, errno %d", rc,  errno);
1403
1404         rc = llapi_layout_comp_extent_get(layout, &s, &e);
1405         ASSERTF(rc == 0, "errno %d", errno);
1406         ASSERTF(s == start[1] && e == end[1],
1407                 "s: %"PRIu64", e: %"PRIu64"", s, e);
1408
1409         rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
1410         ASSERTF(rc == 0, "rc %d, errno %d", rc,  errno);
1411
1412         rc = llapi_layout_comp_del(layout);
1413         ASSERTF(rc == 0, "errno %d", errno);
1414
1415         llapi_layout_free(layout);
1416 }
1417
1418 #define T31FILE         "f31"
1419 #define T31_DESC        "add/delete component to/from existing file"
1420 void test31(void)
1421 {
1422         int rc, fd, i;
1423         uint64_t start[2], end[2];
1424         uint64_t s, e;
1425         uint32_t id[2];
1426         struct llapi_layout *layout;
1427         char path[PATH_MAX];
1428
1429         start[0] = 0;
1430         end[0] = 64 * 1024 * 1024; /* 64m */
1431         start[1] = end[0];
1432         end[1] = LUSTRE_EOF;
1433
1434         if (num_osts < 2)
1435                 return;
1436
1437         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T31FILE);
1438
1439         rc = unlink(path);
1440         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1441
1442         layout = llapi_layout_alloc();
1443         ASSERTF(layout != NULL, "errno %d", errno);
1444
1445         rc = llapi_layout_stripe_count_set(layout, 1);
1446         ASSERTF(rc == 0, "errno %d", errno);
1447
1448         rc = llapi_layout_comp_extent_set(layout, start[0], end[0]);
1449         ASSERTF(rc == 0, "errno %d", errno);
1450
1451         /* create composite file */
1452         fd = llapi_layout_file_create(path, 0, 0660, layout);
1453         ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1454         llapi_layout_free(layout);
1455
1456         layout = llapi_layout_alloc();
1457         ASSERTF(layout != NULL, "errno %d", errno);
1458
1459         rc = llapi_layout_stripe_count_set(layout, 2);
1460         ASSERTF(rc == 0, "errno %d", errno);
1461
1462         rc = llapi_layout_comp_extent_set(layout, start[1], end[1]);
1463         ASSERTF(rc == 0, "errno %d", errno);
1464
1465         /* add comopnent to existing file */
1466         rc = llapi_layout_file_comp_add(path, layout);
1467         ASSERTF(rc == 0, "errno %d", errno);
1468         llapi_layout_free(layout);
1469
1470         /* verify the composite layout after adding */
1471         layout = llapi_layout_get_by_path(path, 0);
1472         ASSERTF(layout != NULL, "errno = %d", errno);
1473
1474         rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1475         ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1476         i = 0;
1477         do {
1478                 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1479                 ASSERTF(rc == 0 && i < 2, "i %d, errno %d", i, errno);
1480                 ASSERTF(s == start[i] && e == end[i],
1481                         "i: %d s: %"PRIu64", e: %"PRIu64"", i, s, e);
1482
1483                 rc = llapi_layout_comp_id_get(layout, &id[i]);
1484                 ASSERTF(rc == 0 && id[i] != 0, "i %d, errno %d, id %d",
1485                         i, errno, id[i]);
1486
1487                 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
1488                 ASSERTF(rc == 0 || i == 1, "i=%d rc=%d errno=%d", i, rc, errno);
1489                 i++;
1490         } while (rc == 0);
1491
1492         /* Verify reverse iteration gives the same IDs as forward iteration */
1493         rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_LAST);
1494         ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1495         do {
1496                 __u32 comp_id;
1497
1498                 --i;
1499                 rc = llapi_layout_comp_id_get(layout, &comp_id);
1500                 ASSERTF(rc == 0 && comp_id == id[i],
1501                         "i %d, errno %d, id[] %u/%u", i, errno, id[i], comp_id);
1502
1503                 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_PREV);
1504                 ASSERTF(rc == 0 || i == 0, "i=%d rc=%d errno=%d", i, rc, errno);
1505         } while (rc == 0);
1506
1507         llapi_layout_free(layout);
1508
1509         /* delete non-tail component will fail */
1510         rc = llapi_layout_file_comp_del(path, id[0], 0);
1511         ASSERTF(rc < 0 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1512
1513         rc = llapi_layout_file_comp_del(path, id[1], 0);
1514         ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1515
1516         /* verify the composite layout after deleting */
1517         layout = llapi_layout_get_by_path(path, 0);
1518         ASSERTF(layout != NULL, "errno = %d", errno);
1519
1520         rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1521         ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1522
1523         rc = llapi_layout_comp_extent_get(layout, &s, &e);
1524         ASSERTF(rc == 0, "errno %d", errno);
1525         ASSERTF(s == start[0] && e == end[0],
1526                 "s: %"PRIu64", e: %"PRIu64"", s, e);
1527 }
1528
1529 #define TEST_DESC_LEN   50
1530 struct test_tbl_entry {
1531         void (*tte_fn)(void);
1532         char tte_desc[TEST_DESC_LEN];
1533         bool tte_skip;
1534 };
1535
1536 static struct test_tbl_entry test_tbl[] = {
1537         { .tte_fn = &test0, .tte_desc = T0_DESC, .tte_skip = false },
1538         { .tte_fn = &test1, .tte_desc = T1_DESC, .tte_skip = false },
1539         { .tte_fn = &test2, .tte_desc = T2_DESC, .tte_skip = false },
1540         { .tte_fn = &test3, .tte_desc = T3_DESC, .tte_skip = false },
1541         { .tte_fn = &test4, .tte_desc = T4_DESC, .tte_skip = false },
1542         { .tte_fn = &test5, .tte_desc = T5_DESC, .tte_skip = false },
1543         { .tte_fn = &test6, .tte_desc = T6_DESC, .tte_skip = false },
1544         { .tte_fn = &test7, .tte_desc = T7_DESC, .tte_skip = false },
1545         { .tte_fn = &test8, .tte_desc = T8_DESC, .tte_skip = false },
1546         { .tte_fn = &test9, .tte_desc = T9_DESC, .tte_skip = false },
1547         { .tte_fn = &test10, .tte_desc = T10_DESC, .tte_skip = false },
1548         { .tte_fn = &test11, .tte_desc = T11_DESC, .tte_skip = false },
1549         { .tte_fn = &test12, .tte_desc = T12_DESC, .tte_skip = false },
1550         { .tte_fn = &test13, .tte_desc = T13_DESC, .tte_skip = false },
1551         { .tte_fn = &test14, .tte_desc = T14_DESC, .tte_skip = false },
1552         { .tte_fn = &test15, .tte_desc = T15_DESC, .tte_skip = false },
1553         { .tte_fn = &test16, .tte_desc = T16_DESC, .tte_skip = false },
1554         { .tte_fn = &test17, .tte_desc = T17_DESC, .tte_skip = false },
1555         { .tte_fn = &test18, .tte_desc = T18_DESC, .tte_skip = false },
1556         { .tte_fn = &test19, .tte_desc = T19_DESC, .tte_skip = false },
1557         { .tte_fn = &test20, .tte_desc = T20_DESC, .tte_skip = false },
1558         { .tte_fn = &test21, .tte_desc = T21_DESC, .tte_skip = false },
1559         { .tte_fn = &test22, .tte_desc = T22_DESC, .tte_skip = false },
1560         { .tte_fn = &test23, .tte_desc = T23_DESC, .tte_skip = false },
1561         { .tte_fn = &test24, .tte_desc = T24_DESC, .tte_skip = false },
1562         { .tte_fn = &test25, .tte_desc = T25_DESC, .tte_skip = false },
1563         { .tte_fn = &test26, .tte_desc = T26_DESC, .tte_skip = false },
1564         { .tte_fn = &test27, .tte_desc = T27_DESC, .tte_skip = false },
1565         { .tte_fn = &test28, .tte_desc = T28_DESC, .tte_skip = false },
1566         { .tte_fn = &test29, .tte_desc = T29_DESC, .tte_skip = false },
1567         { .tte_fn = &test30, .tte_desc = T30_DESC, .tte_skip = false },
1568         { .tte_fn = &test31, .tte_desc = T31_DESC, .tte_skip = false },
1569 };
1570
1571 #define NUM_TESTS       (sizeof(test_tbl) / sizeof(struct test_tbl_entry))
1572
1573 void print_test_desc(int test_num, const char *test_desc, const char *status)
1574 {
1575         int i;
1576
1577         printf(" test %2d: %s ", test_num, test_desc);
1578         for (i = 0; i < TEST_DESC_LEN - strlen(test_desc); i++)
1579                 printf(".");
1580         printf(" %s\n", status);
1581 }
1582
1583 /* This function runs a single test by forking the process.  This way,
1584  * if there is a segfault during a test, the test program won't crash. */
1585 int test(void (*test_fn)(), const char *test_desc, bool test_skip, int test_num)
1586 {
1587         int rc = 0;
1588         pid_t pid;
1589         char status_buf[128];
1590
1591         if (test_skip) {
1592                 print_test_desc(test_num, test_desc, "skip");
1593                 return 0;
1594         }
1595
1596         pid = fork();
1597         if (pid < 0) {
1598                 ERROR("cannot fork: %s", strerror(errno));
1599         } else if (pid > 0) {
1600                 int status = 0;
1601
1602                 /* Non-zero value indicates failure. */
1603                 wait(&status);
1604                 if (status == 0) {
1605                         strncpy(status_buf, "pass", sizeof(status_buf));
1606                 } else if WIFSIGNALED(status) {
1607                         snprintf(status_buf, sizeof(status_buf),
1608                                  "fail (exit status %d, killed by SIG%d)",
1609                                  WEXITSTATUS(status), WTERMSIG(status));
1610                         rc = -1;
1611                 } else {
1612                         snprintf(status_buf, sizeof(status_buf),
1613                                  "fail (exit status %d)", WEXITSTATUS(status));
1614                         rc = -1;
1615                 }
1616                 print_test_desc(test_num, test_desc, status_buf);
1617         } else if (pid == 0) {
1618                 /* Run the test in the child process.  Exit with 0 for success,
1619                  * non-zero for failure */
1620                 test_fn();
1621                 exit(0);
1622         }
1623
1624         return rc;
1625 }
1626
1627 /* 'str_tests' are the tests to be skipped, such as "1,3,4,.." */
1628 static void set_tests_skipped(char *str_tests)
1629 {
1630         char *ptr = str_tests;
1631         int tstno;
1632
1633         if (ptr == NULL || strlen(ptr) == 0)
1634                 return;
1635
1636         while (*ptr != '\0') {
1637                 tstno = strtoul(ptr, &ptr, 0);
1638                 if (tstno >= 0 && tstno < NUM_TESTS)
1639                         test_tbl[tstno].tte_skip = true;
1640                 if (*ptr == ',')
1641                         ptr++;
1642                 else
1643                         break;
1644         }
1645 }
1646
1647 static void process_args(int argc, char *argv[])
1648 {
1649         int c;
1650
1651         while ((c = getopt(argc, argv, "d:p:o:s:")) != -1) {
1652                 switch (c) {
1653                 case 'd':
1654                         lustre_dir = optarg;
1655                         break;
1656                 case 'p':
1657                         poolname = optarg;
1658                         break;
1659                 case 'o':
1660                         num_osts = atoi(optarg);
1661                         break;
1662                 case 's':
1663                         set_tests_skipped(optarg);
1664                         break;
1665                 case '?':
1666                         fprintf(stderr, "Unknown option '%c'\n", optopt);
1667                         usage(argv[0]);
1668                 }
1669         }
1670 }
1671
1672 int main(int argc, char *argv[])
1673 {
1674         int rc = 0;
1675         int i;
1676         struct stat s;
1677         char fsname[8 + 1];
1678
1679         llapi_msg_set_level(LLAPI_MSG_OFF);
1680
1681         process_args(argc, argv);
1682         if (lustre_dir == NULL)
1683                 lustre_dir = "/mnt/lustre";
1684         if (poolname == NULL)
1685                 poolname = "testpool";
1686         if (num_osts == -1)
1687                 num_osts = 2;
1688
1689         if (num_osts < 2)
1690                 DIE("Error: at least 2 OSTS are required\n");
1691
1692         if (stat(lustre_dir, &s) < 0)
1693                 DIE("cannot stat %s: %s\n", lustre_dir, strerror(errno));
1694         else if (!S_ISDIR(s.st_mode))
1695                 DIE("%s: not a directory\n", lustre_dir);
1696
1697         rc = llapi_search_fsname(lustre_dir, fsname);
1698         if (rc != 0) {
1699                 fprintf(stderr, "Error: %s: not a Lustre filesystem\n",
1700                         lustre_dir);
1701                 exit(EXIT_FAILURE);
1702         }
1703
1704         /* Play nice with Lustre test scripts. Non-line buffered output
1705          * stream under I/O redirection may appear incorrectly. */
1706         setvbuf(stdout, NULL, _IOLBF, 0);
1707
1708         for (i = 0; i < NUM_TESTS; i++) {
1709                 struct test_tbl_entry *tst = &test_tbl[i];
1710                 if (test(tst->tte_fn, tst->tte_desc, tst->tte_skip, i) != 0)
1711                         rc++;
1712         }
1713         return rc;
1714 }