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