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