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