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