Whamcloud - gitweb
LU-6913 test: fix conf-sanity test_30b defect
[fs/lustre-release.git] / lustre / tests / llapi_layout_test.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * These tests exercise the llapi_layout API which abstracts the layout
24  * of a Lustre file behind an opaque data type.  They assume a Lustre
25  * file system with at least 2 OSTs and a pool containing at least the
26  * first 2 OSTs.  For example,
27  *
28  *  sudo lctl pool_new lustre.testpool
29  *  sudo lctl pool_add lustre.testpool OST[0-1]
30  *  gcc -Wall -g -Werror -o llapi_layout_test llapi_layout_test.c -llustreapi
31  *  sudo ./llapi_layout_test
32  */
33
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <stdint.h>
38 #include <fcntl.h>
39 #include <sys/wait.h>
40 #include <sys/signal.h>
41 #include <sys/types.h>
42 #include <errno.h>
43 #include <lustre/lustreapi.h>
44 #include <pwd.h>
45 #include <limits.h>
46 #include <sys/stat.h>
47 #include <getopt.h>
48 #include <inttypes.h>
49
50 #define ERROR(fmt, ...)                                                 \
51         fprintf(stderr, "%s: %s:%d: %s: " fmt "\n",                     \
52                 program_invocation_short_name, __FILE__, __LINE__,      \
53                 __func__, ## __VA_ARGS__);
54
55 #define DIE(fmt, ...)                   \
56 do {                                    \
57         ERROR(fmt, ## __VA_ARGS__);     \
58         exit(EXIT_FAILURE);             \
59 } while (0)
60
61 #define ASSERTF(cond, fmt, ...)                                         \
62 do {                                                                    \
63         if (!(cond))                                                    \
64                 DIE("assertion '%s' failed: "fmt, #cond, ## __VA_ARGS__);\
65 } while (0)                                                             \
66
67 static char *lustre_dir;
68 static char *poolname;
69 static int num_osts = -1;
70
71 void usage(char *prog)
72 {
73         printf("Usage: %s [-d lustre_dir] [-p pool_name] [-o num_osts]\n",
74                prog);
75         exit(0);
76 }
77
78 #define T0FILE                  "t0"
79 #define T0_STRIPE_COUNT         num_osts
80 #define T0_STRIPE_SIZE          1048576
81 #define T0_OST_OFFSET           (num_osts - 1)
82 #define T0_DESC         "Read/write layout attributes then create a file"
83 void test0(void)
84 {
85         int rc;
86         int fd;
87         uint64_t count;
88         uint64_t size;
89         struct llapi_layout *layout = llapi_layout_alloc();
90         char path[PATH_MAX];
91         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
92
93         ASSERTF(layout != NULL, "errno %d", errno);
94
95         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
96
97         rc = unlink(path);
98         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
99
100         /* stripe count */
101         rc = llapi_layout_stripe_count_set(layout, T0_STRIPE_COUNT);
102         ASSERTF(rc == 0, "errno = %d", errno);
103         rc = llapi_layout_stripe_count_get(layout, &count);
104         ASSERTF(rc == 0 && count == T0_STRIPE_COUNT, "%"PRIu64" != %d", count,
105                 T0_STRIPE_COUNT);
106
107         /* stripe size */
108         rc = llapi_layout_stripe_size_set(layout, T0_STRIPE_SIZE);
109         ASSERTF(rc == 0, "errno = %d", errno);
110         rc = llapi_layout_stripe_size_get(layout, &size);
111         ASSERTF(rc == 0 && size == T0_STRIPE_SIZE, "%"PRIu64" != %d", size,
112                 T0_STRIPE_SIZE);
113
114         /* pool_name */
115         rc = llapi_layout_pool_name_set(layout, poolname);
116         ASSERTF(rc == 0, "errno = %d", errno);
117         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
118         ASSERTF(rc == 0, "errno = %d", errno);
119         rc = strcmp(mypool, poolname);
120         ASSERTF(rc == 0, "%s != %s", mypool, poolname);
121
122         /* ost_index */
123         rc = llapi_layout_ost_index_set(layout, 0, T0_OST_OFFSET);
124         ASSERTF(rc == 0, "errno = %d", errno);
125
126         /* create */
127         fd = llapi_layout_file_create(path, 0, 0660, layout);
128         ASSERTF(fd >= 0, "path = %s, errno = %d", path, errno);
129         rc = close(fd);
130         ASSERTF(rc == 0, "errno = %d", errno);
131         llapi_layout_free(layout);
132 }
133
134 void __test1_helper(struct llapi_layout *layout)
135 {
136         uint64_t ost0;
137         uint64_t ost1;
138         uint64_t size;
139         uint64_t count;
140         int rc;
141         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
142
143         rc = llapi_layout_stripe_count_get(layout, &count);
144         ASSERTF(count == T0_STRIPE_COUNT, "%"PRIu64" != %d", count,
145                 T0_STRIPE_COUNT);
146
147         rc = llapi_layout_stripe_size_get(layout, &size);
148         ASSERTF(size == T0_STRIPE_SIZE, "%"PRIu64" != %d", size,
149                 T0_STRIPE_SIZE);
150
151         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
152         ASSERTF(rc == 0, "errno = %d", errno);
153         rc = strcmp(mypool, poolname);
154         ASSERTF(rc == 0, "%s != %s", mypool, poolname);
155
156         rc = llapi_layout_ost_index_get(layout, 0, &ost0);
157         ASSERTF(rc == 0, "errno = %d", errno);
158         rc = llapi_layout_ost_index_get(layout, 1, &ost1);
159         ASSERTF(rc == 0, "errno = %d", errno);
160         ASSERTF(ost0 == T0_OST_OFFSET, "%"PRIu64" != %d", ost0, T0_OST_OFFSET);
161         ASSERTF(ost1 != ost0, "%"PRIu64" == %"PRIu64, ost0, ost1);
162 }
163
164 #define T1_DESC         "Read test0 file by path and verify attributes"
165 void test1(void)
166 {
167         char path[PATH_MAX];
168
169         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
170         struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
171         ASSERTF(layout != NULL, "errno = %d", errno);
172         __test1_helper(layout);
173         llapi_layout_free(layout);
174 }
175
176
177 #define T2_DESC         "Read test0 file by FD and verify attributes"
178 void test2(void)
179 {
180         int fd;
181         int rc;
182         char path[PATH_MAX];
183
184         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
185
186         fd = open(path, O_RDONLY);
187         ASSERTF(fd >= 0, "open(%s): errno = %d", path, errno);
188
189         struct llapi_layout *layout = llapi_layout_get_by_fd(fd, 0);
190         ASSERTF(layout != NULL, "errno = %d", errno);
191
192         rc = close(fd);
193         ASSERTF(rc == 0, "close(%s): errno = %d", path, errno);
194
195         __test1_helper(layout);
196         llapi_layout_free(layout);
197 }
198
199 #define T3_DESC         "Read test0 file by FID and verify attributes"
200 void test3(void)
201 {
202         int rc;
203         struct llapi_layout *layout;
204         lustre_fid fid;
205         char fidstr[4096];
206         char path[PATH_MAX];
207
208         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
209
210         rc = llapi_path2fid(path, &fid);
211         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
212         snprintf(fidstr, sizeof(fidstr), "0x%"PRIx64":0x%x:0x%x",
213                  (uint64_t)fid.f_seq, fid.f_oid, fid.f_ver);
214         errno = 0;
215         layout = llapi_layout_get_by_fid(path, &fid, 0);
216         ASSERTF(layout != NULL, "fidstr = %s, errno = %d", fidstr, errno);
217
218         __test1_helper(layout);
219         llapi_layout_free(layout);
220 }
221
222
223 #define T4FILE                  "t4"
224 #define T4_STRIPE_COUNT         2
225 #define T4_STRIPE_SIZE          2097152
226 #define T4_DESC         "Verify compatibility with 'lfs setstripe'"
227 void test4(void)
228 {
229         int rc;
230         uint64_t ost0;
231         uint64_t ost1;
232         uint64_t count;
233         uint64_t size;
234         const char *lfs = getenv("LFS");
235         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
236         char cmd[4096];
237         char path[PATH_MAX];
238
239         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T4FILE);
240
241         if (lfs == NULL)
242                 lfs = "/usr/bin/lfs";
243
244         rc = unlink(path);
245         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
246
247         snprintf(cmd, sizeof(cmd), "%s setstripe %s %s -c %d -s %d %s", lfs,
248                  strlen(poolname) > 0 ? "-p" : "", poolname, T4_STRIPE_COUNT,
249                  T4_STRIPE_SIZE, path);
250         rc = system(cmd);
251         ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
252
253         errno = 0;
254         struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
255         ASSERTF(layout != NULL, "errno = %d", errno);
256
257         rc = llapi_layout_stripe_count_get(layout, &count);
258         ASSERTF(count == T4_STRIPE_COUNT, "%"PRIu64" != %d", count,
259                 T4_STRIPE_COUNT);
260
261         rc = llapi_layout_stripe_size_get(layout, &size);
262         ASSERTF(size == T4_STRIPE_SIZE, "%"PRIu64" != %d", size,
263                 T4_STRIPE_SIZE);
264
265         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
266         ASSERTF(rc == 0, "errno = %d", errno);
267         rc = strcmp(mypool, poolname);
268         ASSERTF(rc == 0, "%s != %s", mypool, poolname);
269
270         rc = llapi_layout_ost_index_get(layout, 0, &ost0);
271         ASSERTF(rc == 0, "errno = %d", errno);
272         rc = llapi_layout_ost_index_get(layout, 1, &ost1);
273         ASSERTF(rc == 0, "errno = %d", errno);
274         ASSERTF(ost1 != ost0, "%"PRIu64" == %"PRIu64, ost0, ost1);
275
276         llapi_layout_free(layout);
277 }
278
279 #define T5FILE          "t5"
280 #define T5_DESC         "llapi_layout_get_by_path ENOENT handling"
281 void test5(void)
282 {
283         int rc;
284         char path[PATH_MAX];
285         struct llapi_layout *layout;
286
287         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T5FILE);
288
289         rc = unlink(path);
290         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
291
292         errno = 0;
293         layout = llapi_layout_get_by_path(path, 0);
294         ASSERTF(layout == NULL && errno == ENOENT, "errno = %d", errno);
295 }
296
297 #define T6_DESC         "llapi_layout_get_by_fd EBADF handling"
298 void test6(void)
299 {
300         errno = 0;
301         struct llapi_layout *layout = llapi_layout_get_by_fd(9999, 0);
302         ASSERTF(layout == NULL && errno == EBADF, "errno = %d", errno);
303 }
304
305
306 #define T7FILE          "t7"
307 #define T7_DESC         "llapi_layout_get_by_path EACCES handling"
308 void test7(void)
309 {
310         int fd;
311         int rc;
312         uid_t myuid = getuid();
313         char path[PATH_MAX];
314         const char *runas = getenv("RUNAS_ID");
315         struct passwd *pw;
316         uid_t uid;
317
318         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T7FILE);
319         ASSERTF(myuid == 0, "myuid = %d", myuid); /* Need root for this test. */
320
321         /* Create file as root */
322         rc = unlink(path);
323         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
324
325         fd = open(path, O_CREAT, 0400);
326         ASSERTF(fd > 0, "errno = %d", errno);
327         rc = close(fd);
328         ASSERTF(rc == 0, "errno = %d", errno);
329
330         /* Become unprivileged user */
331         if (runas != NULL) {
332                 uid = atoi(runas);
333                 ASSERTF(uid != 0, "runas = %s", runas);
334         } else {
335                 pw = getpwnam("nobody");
336                 ASSERTF(pw != NULL, "errno = %d", errno);
337                 uid = pw->pw_uid;
338         }
339         rc = seteuid(uid);
340         ASSERTF(rc == 0, "errno = %d", errno);
341         errno = 0;
342         struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
343         ASSERTF(layout == NULL && errno == EACCES, "errno = %d", errno);
344         rc = seteuid(myuid);
345         ASSERTF(rc == 0, "errno = %d", errno);
346 }
347
348
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 /* Setting pattern > 0 returns EOPNOTSUPP in errno. */
392 #define T9_DESC         "llapi_layout_pattern_set() EOPNOTSUPP handling"
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         errno = 0;
401         rc = llapi_layout_pattern_set(layout, 1);
402         ASSERTF(rc == -1 && errno == EOPNOTSUPP, "rc = %d, errno = %d", rc,
403                 errno);
404         llapi_layout_free(layout);
405 }
406
407
408 /* Verify stripe_count interfaces return errors as expected */
409 #define T10_DESC        "stripe_count error handling"
410 void test10(void)
411 {
412         int rc;
413         uint64_t count;
414         struct llapi_layout *layout;
415
416         layout = llapi_layout_alloc();
417         ASSERTF(layout != NULL, "errno = %d", errno);
418
419         /* invalid stripe count */
420         errno = 0;
421         rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_INVALID);
422         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
423
424         errno = 0;
425         rc = llapi_layout_stripe_count_set(layout, -1);
426         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
427
428         /* NULL layout */
429         errno = 0;
430         rc = llapi_layout_stripe_count_set(NULL, 2);
431         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
432
433         /* NULL layout */
434         errno = 0;
435         rc = llapi_layout_stripe_count_get(NULL, &count);
436         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
437
438         /* NULL count */
439         errno = 0;
440         rc = llapi_layout_stripe_count_get(layout, NULL);
441         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
442
443         /* stripe count too large */
444         errno = 0;
445         rc = llapi_layout_stripe_count_set(layout, LOV_MAX_STRIPE_COUNT + 1);
446         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
447         llapi_layout_free(layout);
448 }
449
450 /* Verify stripe_size interfaces return errors as expected */
451 #define T11_DESC        "stripe_size error handling"
452 void test11(void)
453 {
454         int rc;
455         uint64_t size;
456         struct llapi_layout *layout;
457
458         layout = llapi_layout_alloc();
459         ASSERTF(layout != NULL, "errno = %d", errno);
460
461         /* negative stripe size */
462         errno = 0;
463         rc = llapi_layout_stripe_size_set(layout, -1);
464         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
465
466         /* invalid stripe size */
467         errno = 0;
468         rc = llapi_layout_stripe_size_set(layout, LLAPI_LAYOUT_INVALID);
469         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
470
471         /* stripe size too big */
472         errno = 0;
473         rc = llapi_layout_stripe_size_set(layout, (1ULL << 33));
474         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
475
476         /* NULL layout */
477         errno = 0;
478         rc = llapi_layout_stripe_size_set(NULL, 1048576);
479         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
480
481         errno = 0;
482         rc = llapi_layout_stripe_size_get(NULL, &size);
483         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
484
485         /* NULL size */
486         errno = 0;
487         rc = llapi_layout_stripe_size_get(layout, NULL);
488         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
489
490         llapi_layout_free(layout);
491 }
492
493 /* Verify pool_name interfaces return errors as expected */
494 #define T12_DESC        "pool_name error handling"
495 void test12(void)
496 {
497         int rc;
498         struct llapi_layout *layout;
499         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
500
501         layout = llapi_layout_alloc();
502         ASSERTF(layout != NULL, "errno = %d", errno);
503
504         /* NULL layout */
505         errno = 0;
506         rc = llapi_layout_pool_name_set(NULL, "foo");
507         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
508
509         /* NULL pool name */
510         errno = 0;
511         rc = llapi_layout_pool_name_set(layout, NULL);
512         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
513
514         /* NULL layout */
515         errno = 0;
516         rc = llapi_layout_pool_name_get(NULL, mypool, sizeof(mypool));
517         ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
518
519         /* NULL buffer */
520         errno = 0;
521         rc = llapi_layout_pool_name_get(layout, NULL, sizeof(mypool));
522         ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
523
524         /* Pool name too long*/
525         errno = 0;
526         rc = llapi_layout_pool_name_set(layout, "0123456789abcdef");
527         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
528
529         llapi_layout_free(layout);
530 }
531
532 /* Verify ost_index interface returns errors as expected */
533 #define T13FILE                 "t13"
534 #define T13_STRIPE_COUNT        2
535 #define T13_DESC                "ost_index error handling"
536 void test13(void)
537 {
538         int rc;
539         int fd;
540         uint64_t idx;
541         struct llapi_layout *layout;
542         char path[PATH_MAX];
543
544         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T13FILE);
545
546         layout = llapi_layout_alloc();
547         ASSERTF(layout != NULL, "errno = %d", errno);
548
549         /* Only setting OST index for stripe 0 is supported for now. */
550         errno = 0;
551         rc = llapi_layout_ost_index_set(layout, 1, 1);
552         ASSERTF(rc == -1 && errno == EOPNOTSUPP, "rc = %d, errno = %d",
553                 rc, errno);
554
555         /* invalid OST index */
556         errno = 0;
557         rc = llapi_layout_ost_index_set(layout, 0, LLAPI_LAYOUT_INVALID);
558         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
559
560         errno = 0;
561         rc = llapi_layout_ost_index_set(layout, 0, -1);
562         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
563
564         /* NULL layout */
565         errno = 0;
566         rc = llapi_layout_ost_index_set(NULL, 0, 1);
567         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
568
569         errno = 0;
570         rc = llapi_layout_ost_index_get(NULL, 0, &idx);
571         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
572
573         /* NULL index */
574         errno = 0;
575         rc = llapi_layout_ost_index_get(layout, 0, NULL);
576         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
577
578         /* Layout not read from file so has no OST data. */
579         errno = 0;
580         rc = llapi_layout_stripe_count_set(layout, T13_STRIPE_COUNT);
581         ASSERTF(rc == 0, "errno = %d", errno);
582         rc = llapi_layout_ost_index_get(layout, 0, &idx);
583         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
584
585         /* n greater than stripe count*/
586         rc = unlink(path);
587         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
588         rc = llapi_layout_stripe_count_set(layout, T13_STRIPE_COUNT);
589         ASSERTF(rc == 0, "errno = %d", errno);
590         fd = llapi_layout_file_create(path, 0, 0644, layout);
591         ASSERTF(fd >= 0, "errno = %d", errno);
592         rc = close(fd);
593         ASSERTF(rc == 0, "errno = %d", errno);
594         llapi_layout_free(layout);
595
596         layout = llapi_layout_get_by_path(path, 0);
597         ASSERTF(layout != NULL, "errno = %d", errno);
598         errno = 0;
599         rc = llapi_layout_ost_index_get(layout, T13_STRIPE_COUNT + 1, &idx);
600         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
601
602         llapi_layout_free(layout);
603 }
604
605 /* Verify llapi_layout_file_create() returns errors as expected */
606 #define T14_DESC        "llapi_layout_file_create error handling"
607 void test14(void)
608 {
609         int rc;
610         struct llapi_layout *layout = llapi_layout_alloc();
611
612         /* NULL path */
613         errno = 0;
614         rc = llapi_layout_file_create(NULL, 0, 0, layout);
615         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
616
617         llapi_layout_free(layout);
618 }
619
620 /* Can't change striping attributes of existing file. */
621 #define T15FILE                 "t15"
622 #define T15_STRIPE_COUNT        2
623 #define T15_DESC        "Can't change striping attributes of existing file"
624 void test15(void)
625 {
626         int rc;
627         int fd;
628         uint64_t count;
629         struct llapi_layout *layout;
630         char path[PATH_MAX];
631
632         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T15FILE);
633
634         rc = unlink(path);
635         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
636
637         layout = llapi_layout_alloc();
638         ASSERTF(layout != NULL, "errno = %d", errno);
639         rc = llapi_layout_stripe_count_set(layout, T15_STRIPE_COUNT);
640         ASSERTF(rc == 0, "errno = %d", errno);
641
642         errno = 0;
643         fd = llapi_layout_file_create(path, 0, 0640, layout);
644         ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
645         rc = close(fd);
646         ASSERTF(rc == 0, "errno = %d", errno);
647
648         rc = llapi_layout_stripe_count_set(layout, T15_STRIPE_COUNT - 1);
649         errno = 0;
650         fd = llapi_layout_file_open(path, 0, 0640, layout);
651         ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
652         rc = close(fd);
653         ASSERTF(rc == 0, "errno = %d", errno);
654         llapi_layout_free(layout);
655
656         layout = llapi_layout_get_by_path(path, 0);
657         ASSERTF(layout != NULL, "errno = %d", errno);
658         rc = llapi_layout_stripe_count_get(layout, &count);
659         ASSERTF(rc == 0 && count == T15_STRIPE_COUNT,
660                 "rc = %d, %"PRIu64" != %d", rc, count, T15_STRIPE_COUNT);
661         llapi_layout_free(layout);
662 }
663
664 /* Default stripe attributes are applied as expected. */
665 #define T16FILE         "t16"
666 #define T16_DESC        "Default stripe attributes are applied as expected"
667 void test16(void)
668 {
669         int             rc;
670         int             fd;
671         struct llapi_layout     *deflayout;
672         struct llapi_layout     *filelayout;
673         char            path[PATH_MAX];
674         uint64_t        fsize;
675         uint64_t        fcount;
676         uint64_t        dsize;
677         uint64_t        dcount;
678
679         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T16FILE);
680
681         rc = unlink(path);
682         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
683
684         deflayout = llapi_layout_get_by_path(lustre_dir, LAYOUT_GET_EXPECTED);
685         ASSERTF(deflayout != NULL, "errno = %d", errno);
686         rc = llapi_layout_stripe_size_get(deflayout, &dsize);
687         ASSERTF(rc == 0, "errno = %d", errno);
688         rc = llapi_layout_stripe_count_get(deflayout, &dcount);
689         ASSERTF(rc == 0, "errno = %d", errno);
690
691         /* First, with a default struct llapi_layout */
692         filelayout = llapi_layout_alloc();
693         ASSERTF(filelayout != NULL, "errno = %d", errno);
694
695         fd = llapi_layout_file_create(path, 0, 0640, filelayout);
696         ASSERTF(fd >= 0, "errno = %d", errno);
697
698         rc = close(fd);
699         ASSERTF(rc == 0, "errno = %d", errno);
700
701         llapi_layout_free(filelayout);
702
703         filelayout = llapi_layout_get_by_path(path, 0);
704         ASSERTF(filelayout != NULL, "errno = %d", errno);
705
706         rc = llapi_layout_stripe_count_get(filelayout, &fcount);
707         ASSERTF(rc == 0, "errno = %d", errno);
708         ASSERTF(fcount == dcount, "%"PRIu64" != %"PRIu64, fcount, dcount);
709
710         rc = llapi_layout_stripe_size_get(filelayout, &fsize);
711         ASSERTF(rc == 0, "errno = %d", errno);
712         ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
713
714         /* NULL layout also implies default layout */
715         rc = unlink(path);
716         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
717
718         fd = llapi_layout_file_create(path, 0, 0640, filelayout);
719         ASSERTF(fd >= 0, "errno = %d", errno);
720         rc = close(fd);
721         ASSERTF(rc == 0, "errno = %d", errno);
722         filelayout = llapi_layout_get_by_path(path, 0);
723         ASSERTF(filelayout != NULL, "errno = %d", errno);
724
725         rc = llapi_layout_stripe_count_get(filelayout, &fcount);
726         ASSERTF(rc == 0, "errno = %d", errno);
727         rc = llapi_layout_stripe_size_get(filelayout, &fsize);
728         ASSERTF(rc == 0, "errno = %d", errno);
729         ASSERTF(fcount == dcount, "%"PRIu64" != %"PRIu64, fcount, dcount);
730         ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
731
732         llapi_layout_free(filelayout);
733         llapi_layout_free(deflayout);
734 }
735
736 /* Setting stripe count to LLAPI_LAYOUT_WIDE uses all available OSTs. */
737 #define T17FILE         "t17"
738 #define T17_DESC        "LLAPI_LAYOUT_WIDE is honored"
739 void test17(void)
740 {
741         int rc;
742         int fd;
743         int osts_all;
744         uint64_t osts_layout;
745         struct llapi_layout *layout;
746         char path[PATH_MAX];
747
748         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T17FILE);
749
750         rc = unlink(path);
751         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
752         layout = llapi_layout_alloc();
753         ASSERTF(layout != NULL, "errno = %d", errno);
754         rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_WIDE);
755         ASSERTF(rc == 0, "errno = %d", errno);
756         fd = llapi_layout_file_create(path, 0, 0640, layout);
757         ASSERTF(fd >= 0, "errno = %d", errno);
758         rc = close(fd);
759         ASSERTF(rc == 0, "errno = %d", errno);
760         llapi_layout_free(layout);
761
762         /* Get number of available OSTs */
763         fd = open(path, O_RDONLY);
764         ASSERTF(fd >= 0, "errno = %d", errno);
765         rc = llapi_lov_get_uuids(fd, NULL, &osts_all);
766         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
767         rc = close(fd);
768         ASSERTF(rc == 0, "errno = %d", errno);
769
770         layout = llapi_layout_get_by_path(path, 0);
771         ASSERTF(layout != NULL, "errno = %d", errno);
772         rc = llapi_layout_stripe_count_get(layout, &osts_layout);
773         ASSERTF(osts_layout == osts_all, "%"PRIu64" != %d", osts_layout,
774                 osts_all);
775
776         llapi_layout_free(layout);
777 }
778
779 /* Setting pool with "fsname.pool" notation. */
780 #define T18FILE         "t18"
781 #define T18_DESC        "Setting pool with fsname.pool notation"
782 void test18(void)
783 {
784         int rc;
785         int fd;
786         struct llapi_layout *layout = llapi_layout_alloc();
787         char path[PATH_MAX];
788         char pool[LOV_MAXPOOLNAME*2 + 1];
789         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
790
791         snprintf(pool, sizeof(pool), "lustre.%s", poolname);
792
793         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T18FILE);
794
795         ASSERTF(layout != NULL, "errno = %d", errno);
796
797         rc = unlink(path);
798         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
799
800         rc = llapi_layout_pool_name_set(layout, pool);
801         ASSERTF(rc == 0, "errno = %d", errno);
802
803         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
804         ASSERTF(rc == 0, "errno = %d", errno);
805         rc = strcmp(mypool, poolname);
806         ASSERTF(rc == 0, "%s != %s", mypool, poolname);
807         fd = llapi_layout_file_create(path, 0, 0640, layout);
808         ASSERTF(fd >= 0, "errno = %d", errno);
809         rc = close(fd);
810         ASSERTF(rc == 0, "errno = %d", errno);
811
812         llapi_layout_free(layout);
813
814         layout = llapi_layout_get_by_path(path, 0);
815         ASSERTF(layout != NULL, "errno = %d", errno);
816         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
817         ASSERTF(rc == 0, "errno = %d", errno);
818         rc = strcmp(mypool, poolname);
819         ASSERTF(rc == 0, "%s != %s", mypool, poolname);
820         llapi_layout_free(layout);
821 }
822
823 #define T19_DESC        "Maximum length pool name is NULL-terminated"
824 void test19(void)
825 {
826         struct llapi_layout *layout;
827         char *name = "0123456789abcde";
828         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
829         int rc;
830
831         layout = llapi_layout_alloc();
832         ASSERTF(layout != NULL, "errno = %d", errno);
833         rc = llapi_layout_pool_name_set(layout, name);
834         ASSERTF(rc == 0, "errno = %d", errno);
835         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
836         ASSERTF(strlen(name) == strlen(mypool), "name = %s, str = %s", name,
837                 mypool);
838         llapi_layout_free(layout);
839 }
840
841 #define T20FILE         "t20"
842 #define T20_DESC        "LLAPI_LAYOUT_DEFAULT is honored"
843 void test20(void)
844 {
845         int             rc;
846         int             fd;
847         struct llapi_layout     *deflayout;
848         struct llapi_layout     *filelayout;
849         char            path[PATH_MAX];
850         uint64_t        fsize;
851         uint64_t        fcount;
852         uint64_t        dsize;
853         uint64_t        dcount;
854
855         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T20FILE);
856
857         rc = unlink(path);
858         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
859
860         filelayout = llapi_layout_alloc();
861         ASSERTF(filelayout != NULL, "errno = %d", errno);
862
863         rc = llapi_layout_stripe_size_set(filelayout, LLAPI_LAYOUT_DEFAULT);
864         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
865
866         rc = llapi_layout_stripe_count_set(filelayout, LLAPI_LAYOUT_DEFAULT);
867         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
868
869         fd = llapi_layout_file_create(path, 0, 0640, filelayout);
870         ASSERTF(fd >= 0, "errno = %d", errno);
871
872         rc = close(fd);
873         ASSERTF(rc == 0, "errno = %d", errno);
874
875         llapi_layout_free(filelayout);
876
877         deflayout = llapi_layout_get_by_path(lustre_dir, LAYOUT_GET_EXPECTED);
878         ASSERTF(deflayout != NULL, "errno = %d", errno);
879
880         filelayout = llapi_layout_get_by_path(path, 0);
881         ASSERTF(filelayout != NULL, "errno = %d", errno);
882
883         rc = llapi_layout_stripe_count_get(filelayout, &fcount);
884         ASSERTF(rc == 0, "errno = %d", errno);
885         rc = llapi_layout_stripe_count_get(deflayout, &dcount);
886         ASSERTF(rc == 0, "errno = %d", errno);
887         ASSERTF(fcount == dcount, "%"PRIu64" != %"PRIu64, fcount, dcount);
888
889         rc = llapi_layout_stripe_size_get(filelayout, &fsize);
890         ASSERTF(rc == 0, "errno = %d", errno);
891         rc = llapi_layout_stripe_size_get(deflayout, &dsize);
892         ASSERTF(rc == 0, "errno = %d", errno);
893         ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
894
895         llapi_layout_free(filelayout);
896         llapi_layout_free(deflayout);
897 }
898
899 #define T21_DESC        "llapi_layout_file_create fails for non-Lustre file"
900 void test21(void)
901 {
902         struct llapi_layout *layout;
903         char template[PATH_MAX];
904         int fd;
905         int rc;
906
907         snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
908         fd = mkstemp(template);
909         ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
910         rc = close(fd);
911         ASSERTF(rc == 0, "errno = %d", fd);
912         rc = unlink(template);
913         ASSERTF(rc == 0, "errno = %d", errno);
914
915         layout = llapi_layout_alloc();
916         ASSERTF(layout != NULL, "errno = %d", errno);
917
918         fd = llapi_layout_file_create(template, 0, 0640, layout);
919         ASSERTF(fd == -1 && errno == ENOTTY,
920                 "fd = %d, errno = %d, template = %s", fd, errno, template);
921         llapi_layout_free(layout);
922 }
923
924 #define T22FILE         "t22"
925 #define T22_DESC        "llapi_layout_file_create applied mode correctly"
926 void test22(void)
927 {
928         int             rc;
929         int             fd;
930         char            path[PATH_MAX];
931         struct stat     st;
932         mode_t          mode_in = 0640;
933         mode_t          mode_out;
934         mode_t          umask_orig;
935
936         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T22FILE);
937
938         rc = unlink(path);
939         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
940
941         umask_orig = umask(S_IWGRP | S_IWOTH);
942
943         fd = llapi_layout_file_create(path, 0, mode_in, NULL);
944         ASSERTF(fd >= 0, "errno = %d", errno);
945
946         (void) umask(umask_orig);
947
948         rc = fstat(fd, &st);
949         ASSERTF(rc == 0, "errno = %d", errno);
950
951         rc = close(fd);
952         ASSERTF(rc == 0, "errno = %d", fd);
953
954         mode_out = st.st_mode & ~S_IFMT;
955         ASSERTF(mode_in == mode_out, "%o != %o", mode_in, mode_out);
956 }
957
958 #define T23_DESC        "llapi_layout_get_by_path fails for non-Lustre file"
959 void test23(void)
960 {
961         struct llapi_layout *layout;
962         char template[PATH_MAX];
963         int fd;
964         int rc;
965
966         snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
967         fd = mkstemp(template);
968         ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
969         rc = close(fd);
970         ASSERTF(rc == 0, "errno = %d", fd);
971
972         layout = llapi_layout_get_by_path(template, 0);
973         ASSERTF(layout == NULL && errno == ENOTTY,
974                 "errno = %d, template = %s", errno, template);
975
976         rc = unlink(template);
977         ASSERTF(rc == 0, "errno = %d", errno);
978 }
979
980 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
981  * for file with unspecified layout. */
982 #define T24FILE         "t24"
983 #define T24_DESC        "LAYOUT_GET_EXPECTED works with existing file"
984 void test24(void)
985 {
986         int fd;
987         int rc;
988         struct llapi_layout *layout;
989         uint64_t count;
990         uint64_t size;
991         uint64_t pattern;
992         char path[PATH_MAX];
993
994         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T24FILE);
995
996         rc = unlink(path);
997         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
998         fd = open(path, O_CREAT, 0640);
999         ASSERTF(fd >= 0, "errno = %d", errno);
1000         rc = close(fd);
1001         ASSERTF(rc == 0, "errno = %d", errno);
1002
1003         layout = llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED);
1004         ASSERTF(layout != NULL, "errno = %d\n", errno);
1005
1006         rc = llapi_layout_stripe_count_get(layout, &count);
1007         ASSERTF(rc == 0, "errno = %d\n", errno);
1008         ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1009
1010         rc = llapi_layout_stripe_size_get(layout, &size);
1011         ASSERTF(rc == 0, "errno = %d\n", errno);
1012         ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1013
1014         rc = llapi_layout_pattern_get(layout, &pattern);
1015         ASSERTF(rc == 0, "errno = %d\n", errno);
1016         ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1017
1018         llapi_layout_free(layout);
1019 }
1020
1021 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
1022  * for directory with unspecified layout. */
1023 #define T25DIR          "d25"
1024 #define T25_DESC        "LAYOUT_GET_EXPECTED works with directory"
1025 void test25(void)
1026 {
1027         int rc;
1028         struct llapi_layout *layout;
1029         uint64_t count;
1030         uint64_t size;
1031         uint64_t pattern;
1032         char dir[PATH_MAX];
1033
1034         snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T25DIR);
1035
1036         rc = rmdir(dir);
1037         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1038         rc = mkdir(dir, 0750);
1039         ASSERTF(rc == 0, "errno = %d", errno);
1040
1041         layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1042         ASSERTF(layout != NULL, "errno = %d\n", errno);
1043
1044         rc = llapi_layout_stripe_count_get(layout, &count);
1045         ASSERTF(rc == 0, "errno = %d\n", errno);
1046         ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1047
1048         rc = llapi_layout_stripe_size_get(layout, &size);
1049         ASSERTF(rc == 0, "errno = %d\n", errno);
1050         ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1051
1052         rc = llapi_layout_pattern_get(layout, &pattern);
1053         ASSERTF(rc == 0, "errno = %d\n", errno);
1054         ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1055
1056         llapi_layout_free(layout);
1057 }
1058
1059 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) correctly combines
1060  * specified attributes of parent directory with attributes filesystem root. */
1061 #define T26DIR          "d26"
1062 #define T26_DESC        "LAYOUT_GET_EXPECTED partially specified parent"
1063 #define T26_STRIPE_SIZE (1048576 * 4)
1064 void test26(void)
1065 {
1066         int rc;
1067         struct llapi_layout *layout;
1068         const char *lfs = getenv("LFS");
1069         uint64_t count;
1070         uint64_t size;
1071         uint64_t pattern;
1072         char dir[PATH_MAX];
1073         char cmd[4096];
1074
1075         snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T26DIR);
1076         rc = rmdir(dir);
1077         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1078         rc = mkdir(dir, 0750);
1079         ASSERTF(rc == 0, "errno = %d", errno);
1080
1081         if (lfs == NULL)
1082                 lfs = "/usr/bin/lfs";
1083
1084         snprintf(cmd, sizeof(cmd), "%s setstripe -s %d %s", lfs,
1085                  T26_STRIPE_SIZE, dir);
1086         rc = system(cmd);
1087         ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1088
1089         layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1090         ASSERTF(layout != NULL, "errno = %d\n", errno);
1091
1092         rc = llapi_layout_stripe_count_get(layout, &count);
1093         ASSERTF(rc == 0, "errno = %d\n", errno);
1094         ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1095
1096         rc = llapi_layout_stripe_size_get(layout, &size);
1097         ASSERTF(rc == 0, "errno = %d\n", errno);
1098         ASSERTF(size == T26_STRIPE_SIZE, "size = %"PRIu64, size);
1099
1100         rc = llapi_layout_pattern_get(layout, &pattern);
1101         ASSERTF(rc == 0, "errno = %d\n", errno);
1102         ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1103
1104         llapi_layout_free(layout);
1105 }
1106
1107 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) work with
1108  * non existing file. */
1109 #define T27DIR          "d27"
1110 #define T27_DESC        "LAYOUT_GET_EXPECTED with non existing file"
1111 #define T27_STRIPE_SIZE (1048576 * 3)
1112 void test27(void)
1113 {
1114         int rc;
1115         struct llapi_layout *layout;
1116         const char *lfs = getenv("LFS");
1117         uint64_t count;
1118         uint64_t size;
1119         uint64_t pattern;
1120         char dirpath[PATH_MAX];
1121         char filepath[PATH_MAX];
1122         char cmd[4096];
1123
1124         snprintf(dirpath, sizeof(dirpath), "%s/%s", lustre_dir, T27DIR);
1125         snprintf(filepath, sizeof(filepath), "%s/nonesuch", dirpath);
1126
1127         rc = rmdir(dirpath);
1128         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1129         rc = mkdir(dirpath, 0750);
1130         ASSERTF(rc == 0, "errno = %d", errno);
1131
1132         if (lfs == NULL)
1133                 lfs = "/usr/bin/lfs";
1134
1135         snprintf(cmd, sizeof(cmd), "%s setstripe -s %d %s", lfs,
1136                  T27_STRIPE_SIZE, dirpath);
1137         rc = system(cmd);
1138         ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1139
1140         layout = llapi_layout_get_by_path(filepath, LAYOUT_GET_EXPECTED);
1141         ASSERTF(layout != NULL, "errno = %d\n", errno);
1142
1143         rc = llapi_layout_stripe_count_get(layout, &count);
1144         ASSERTF(rc == 0, "errno = %d\n", errno);
1145         ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1146
1147         rc = llapi_layout_stripe_size_get(layout, &size);
1148         ASSERTF(rc == 0, "errno = %d\n", errno);
1149         ASSERTF(size == T27_STRIPE_SIZE, "size = %"PRIu64, size);
1150
1151         rc = llapi_layout_pattern_get(layout, &pattern);
1152         ASSERTF(rc == 0, "errno = %d\n", errno);
1153         ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1154
1155         llapi_layout_free(layout);
1156 }
1157
1158 /* llapi_layout_stripe_count_get returns LLAPI_LAYOUT_WIDE for a directory
1159  * with a stripe_count of -1. */
1160 #define T28DIR          "d28"
1161 #define T28_DESC        "LLAPI_LAYOUT_WIDE returned as expected"
1162 void test28(void)
1163 {
1164         int rc;
1165         struct llapi_layout *layout;
1166         const char *lfs = getenv("LFS");
1167         uint64_t count;
1168         char dirpath[PATH_MAX];
1169         char cmd[4096];
1170
1171         snprintf(dirpath, sizeof(dirpath), "%s/%s", lustre_dir, T28DIR);
1172
1173         rc = rmdir(dirpath);
1174         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1175         rc = mkdir(dirpath, 0750);
1176         ASSERTF(rc == 0, "errno = %d", errno);
1177
1178         if (lfs == NULL)
1179                 lfs = "/usr/bin/lfs";
1180
1181         snprintf(cmd, sizeof(cmd), "%s setstripe -c -1 %s", lfs, dirpath);
1182         rc = system(cmd);
1183         ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1184
1185         layout = llapi_layout_get_by_path(dirpath, 0);
1186         ASSERTF(layout != NULL, "errno = %d\n", errno);
1187
1188         rc = llapi_layout_stripe_count_get(layout, &count);
1189         ASSERTF(rc == 0, "errno = %d\n", errno);
1190         ASSERTF(count == LLAPI_LAYOUT_WIDE, "count = %"PRIu64"\n", count);
1191
1192         llapi_layout_free(layout);
1193 }
1194
1195 #define TEST_DESC_LEN   50
1196 struct test_tbl_entry {
1197         void (*tte_fn)(void);
1198         char tte_desc[TEST_DESC_LEN];
1199         bool tte_skip;
1200 };
1201
1202 static struct test_tbl_entry test_tbl[] = {
1203         { &test0,  T0_DESC, false },
1204         { &test1,  T1_DESC, false },
1205         { &test2,  T2_DESC, false },
1206         { &test3,  T3_DESC, false },
1207         { &test4,  T4_DESC, false },
1208         { &test5,  T5_DESC, false },
1209         { &test6,  T6_DESC, false },
1210         { &test7,  T7_DESC, false },
1211         { &test8,  T8_DESC, false },
1212         { &test9,  T9_DESC, false },
1213         { &test10, T10_DESC, false },
1214         { &test11, T11_DESC, false },
1215         { &test12, T12_DESC, false },
1216         { &test13, T13_DESC, false },
1217         { &test14, T14_DESC, false },
1218         { &test15, T15_DESC, false },
1219         { &test16, T16_DESC, false },
1220         { &test17, T17_DESC, false },
1221         { &test18, T18_DESC, false },
1222         { &test19, T19_DESC, false },
1223         { &test20, T20_DESC, false },
1224         { &test21, T21_DESC, false },
1225         { &test22, T22_DESC, false },
1226         { &test23, T23_DESC, false },
1227         { &test24, T24_DESC, false },
1228         { &test25, T25_DESC, false },
1229         { &test26, T26_DESC, false },
1230         { &test27, T27_DESC, false },
1231         { &test28, T28_DESC, false },
1232 };
1233 #define NUM_TESTS       (sizeof(test_tbl) / sizeof(struct test_tbl_entry))
1234
1235 void print_test_desc(int test_num, const char *test_desc, const char *status)
1236 {
1237         int i;
1238
1239         printf(" test %2d: %s ", test_num, test_desc);
1240         for (i = 0; i < TEST_DESC_LEN - strlen(test_desc); i++)
1241                 printf(".");
1242         printf(" %s\n", status);
1243 }
1244
1245 /* This function runs a single test by forking the process.  This way,
1246  * if there is a segfault during a test, the test program won't crash. */
1247 int test(void (*test_fn)(), const char *test_desc, bool test_skip, int test_num)
1248 {
1249         int rc = 0;
1250         pid_t pid;
1251         char status_buf[128];
1252
1253         if (test_skip) {
1254                 print_test_desc(test_num, test_desc, "skip");
1255                 return 0;
1256         }
1257
1258         pid = fork();
1259         if (pid < 0) {
1260                 ERROR("cannot fork: %s", strerror(errno));
1261         } else if (pid > 0) {
1262                 int status = 0;
1263
1264                 /* Non-zero value indicates failure. */
1265                 wait(&status);
1266                 if (status == 0) {
1267                         strncpy(status_buf, "pass", sizeof(status_buf));
1268                 } else if WIFSIGNALED(status) {
1269                         snprintf(status_buf, sizeof(status_buf),
1270                                  "fail (exit status %d, killed by SIG%d)",
1271                                  WEXITSTATUS(status), WTERMSIG(status));
1272                         rc = -1;
1273                 } else {
1274                         snprintf(status_buf, sizeof(status_buf),
1275                                  "fail (exit status %d)", WEXITSTATUS(status));
1276                         rc = -1;
1277                 }
1278                 print_test_desc(test_num, test_desc, status_buf);
1279         } else if (pid == 0) {
1280                 /* Run the test in the child process.  Exit with 0 for success,
1281                  * non-zero for failure */
1282                 test_fn();
1283                 exit(0);
1284         }
1285
1286         return rc;
1287 }
1288
1289 static void process_args(int argc, char *argv[])
1290 {
1291         int c;
1292
1293         while ((c = getopt(argc, argv, "d:p:o:")) != -1) {
1294                 switch (c) {
1295                 case 'd':
1296                         lustre_dir = optarg;
1297                         break;
1298                 case 'p':
1299                         poolname = optarg;
1300                         break;
1301                 case 'o':
1302                         num_osts = atoi(optarg);
1303                         break;
1304                 case '?':
1305                         fprintf(stderr, "Unknown option '%c'\n", optopt);
1306                         usage(argv[0]);
1307                 }
1308         }
1309 }
1310
1311 int main(int argc, char *argv[])
1312 {
1313         int rc = 0;
1314         int i;
1315         struct stat s;
1316         char fsname[8 + 1];
1317
1318         llapi_msg_set_level(LLAPI_MSG_OFF);
1319
1320         process_args(argc, argv);
1321         if (lustre_dir == NULL)
1322                 lustre_dir = "/mnt/lustre";
1323         if (poolname == NULL)
1324                 poolname = "testpool";
1325         if (num_osts == -1)
1326                 num_osts = 2;
1327
1328         if (num_osts < 2)
1329                 DIE("Error: at least 2 OSTS are required\n");
1330
1331         if (stat(lustre_dir, &s) < 0)
1332                 DIE("cannot stat %s: %s\n", lustre_dir, strerror(errno));
1333         else if (!S_ISDIR(s.st_mode))
1334                 DIE("%s: not a directory\n", lustre_dir);
1335
1336         rc = llapi_search_fsname(lustre_dir, fsname);
1337         if (rc != 0) {
1338                 fprintf(stderr, "Error: %s: not a Lustre filesystem\n",
1339                         lustre_dir);
1340                 exit(EXIT_FAILURE);
1341         }
1342
1343         /* Play nice with Lustre test scripts. Non-line buffered output
1344          * stream under I/O redirection may appear incorrectly. */
1345         setvbuf(stdout, NULL, _IOLBF, 0);
1346
1347         for (i = 0; i < NUM_TESTS; i++) {
1348                 struct test_tbl_entry *tst = &test_tbl[i];
1349                 if (test(tst->tte_fn, tst->tte_desc, tst->tte_skip, i) != 0)
1350                         rc++;
1351         }
1352         return rc;
1353 }