Whamcloud - gitweb
9d4dac6bb3056e49a3be6a71b52c08d31daf5dc6
[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] "
74                "[-s $n,$m,..]\n", 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 #define T2_DESC         "Read test0 file by FD and verify attributes"
177 void test2(void)
178 {
179         int fd;
180         int rc;
181         char path[PATH_MAX];
182
183         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
184
185         fd = open(path, O_RDONLY);
186         ASSERTF(fd >= 0, "open(%s): errno = %d", path, errno);
187
188         struct llapi_layout *layout = llapi_layout_get_by_fd(fd, 0);
189         ASSERTF(layout != NULL, "errno = %d", errno);
190
191         rc = close(fd);
192         ASSERTF(rc == 0, "close(%s): errno = %d", path, errno);
193
194         __test1_helper(layout);
195         llapi_layout_free(layout);
196 }
197
198 #define T3_DESC         "Read test0 file by FID and verify attributes"
199 void test3(void)
200 {
201         int rc;
202         struct llapi_layout *layout;
203         lustre_fid fid;
204         char fidstr[4096];
205         char path[PATH_MAX];
206
207         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
208
209         rc = llapi_path2fid(path, &fid);
210         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
211         snprintf(fidstr, sizeof(fidstr), "0x%"PRIx64":0x%x:0x%x",
212                  (uint64_t)fid.f_seq, fid.f_oid, fid.f_ver);
213         errno = 0;
214         layout = llapi_layout_get_by_fid(path, &fid, 0);
215         ASSERTF(layout != NULL, "fidstr = %s, errno = %d", fidstr, errno);
216
217         __test1_helper(layout);
218         llapi_layout_free(layout);
219 }
220
221 #define T4FILE                  "t4"
222 #define T4_STRIPE_COUNT         2
223 #define T4_STRIPE_SIZE          2097152
224 #define T4_DESC         "Verify compatibility with 'lfs setstripe'"
225 void test4(void)
226 {
227         int rc;
228         uint64_t ost0;
229         uint64_t ost1;
230         uint64_t count;
231         uint64_t size;
232         const char *lfs = getenv("LFS");
233         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
234         char cmd[4096];
235         char path[PATH_MAX];
236
237         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T4FILE);
238
239         if (lfs == NULL)
240                 lfs = "/usr/bin/lfs";
241
242         rc = unlink(path);
243         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
244
245         snprintf(cmd, sizeof(cmd), "%s setstripe %s %s -c %d -s %d %s", lfs,
246                  strlen(poolname) > 0 ? "-p" : "", poolname, T4_STRIPE_COUNT,
247                  T4_STRIPE_SIZE, path);
248         rc = system(cmd);
249         ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
250
251         errno = 0;
252         struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
253         ASSERTF(layout != NULL, "errno = %d", errno);
254
255         rc = llapi_layout_stripe_count_get(layout, &count);
256         ASSERTF(count == T4_STRIPE_COUNT, "%"PRIu64" != %d", count,
257                 T4_STRIPE_COUNT);
258
259         rc = llapi_layout_stripe_size_get(layout, &size);
260         ASSERTF(size == T4_STRIPE_SIZE, "%"PRIu64" != %d", size,
261                 T4_STRIPE_SIZE);
262
263         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
264         ASSERTF(rc == 0, "errno = %d", errno);
265         rc = strcmp(mypool, poolname);
266         ASSERTF(rc == 0, "%s != %s", mypool, poolname);
267
268         rc = llapi_layout_ost_index_get(layout, 0, &ost0);
269         ASSERTF(rc == 0, "errno = %d", errno);
270         rc = llapi_layout_ost_index_get(layout, 1, &ost1);
271         ASSERTF(rc == 0, "errno = %d", errno);
272         ASSERTF(ost1 != ost0, "%"PRIu64" == %"PRIu64, ost0, ost1);
273
274         llapi_layout_free(layout);
275 }
276
277 #define T5FILE          "t5"
278 #define T5_DESC         "llapi_layout_get_by_path ENOENT handling"
279 void test5(void)
280 {
281         int rc;
282         char path[PATH_MAX];
283         struct llapi_layout *layout;
284
285         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T5FILE);
286
287         rc = unlink(path);
288         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
289
290         errno = 0;
291         layout = llapi_layout_get_by_path(path, 0);
292         ASSERTF(layout == NULL && errno == ENOENT, "errno = %d", errno);
293 }
294
295 #define T6_DESC         "llapi_layout_get_by_fd EBADF handling"
296 void test6(void)
297 {
298         errno = 0;
299         struct llapi_layout *layout = llapi_layout_get_by_fd(9999, 0);
300         ASSERTF(layout == NULL && errno == EBADF, "errno = %d", errno);
301 }
302
303 #define T7FILE          "t7"
304 #define T7_DESC         "llapi_layout_get_by_path EACCES handling"
305 void test7(void)
306 {
307         int fd;
308         int rc;
309         uid_t myuid = getuid();
310         char path[PATH_MAX];
311         const char *runas = getenv("RUNAS_ID");
312         struct passwd *pw;
313         uid_t uid;
314
315         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T7FILE);
316         ASSERTF(myuid == 0, "myuid = %d", myuid); /* Need root for this test. */
317
318         /* Create file as root */
319         rc = unlink(path);
320         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
321
322         fd = open(path, O_CREAT, 0400);
323         ASSERTF(fd > 0, "errno = %d", errno);
324         rc = close(fd);
325         ASSERTF(rc == 0, "errno = %d", errno);
326
327         /* Become unprivileged user */
328         if (runas != NULL) {
329                 uid = atoi(runas);
330                 ASSERTF(uid != 0, "runas = %s", runas);
331         } else {
332                 pw = getpwnam("nobody");
333                 ASSERTF(pw != NULL, "errno = %d", errno);
334                 uid = pw->pw_uid;
335         }
336         rc = seteuid(uid);
337         ASSERTF(rc == 0, "errno = %d", errno);
338         errno = 0;
339         struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
340         ASSERTF(layout == NULL && errno == EACCES, "errno = %d", errno);
341         rc = seteuid(myuid);
342         ASSERTF(rc == 0, "errno = %d", errno);
343 }
344
345 /* llapi_layout_get_by_path() returns default layout for file with no
346  * striping attributes. */
347 #define T8FILE          "t8"
348 #define T8_DESC         "llapi_layout_get_by_path ENODATA handling"
349 void test8(void)
350 {
351         int fd;
352         int rc;
353         struct llapi_layout *layout;
354         uint64_t count;
355         uint64_t size;
356         uint64_t pattern;
357         char path[PATH_MAX];
358
359         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T8FILE);
360
361         rc = unlink(path);
362         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
363         fd = open(path, O_CREAT, 0640);
364         ASSERTF(fd >= 0, "errno = %d", errno);
365         rc = close(fd);
366         ASSERTF(rc == 0, "errno = %d", errno);
367
368         layout = llapi_layout_get_by_path(path, 0);
369         ASSERTF(layout != NULL, "errno = %d\n", errno);
370
371         rc = llapi_layout_stripe_count_get(layout, &count);
372         ASSERTF(rc == 0, "errno = %d\n", errno);
373         ASSERTF(count == LLAPI_LAYOUT_DEFAULT, "count = %"PRIu64"\n", count);
374
375         rc = llapi_layout_stripe_size_get(layout, &size);
376         ASSERTF(rc == 0, "errno = %d\n", errno);
377         ASSERTF(size == LLAPI_LAYOUT_DEFAULT, "size = %"PRIu64"\n", size);
378
379         rc = llapi_layout_pattern_get(layout, &pattern);
380         ASSERTF(rc == 0, "errno = %d\n", errno);
381         ASSERTF(pattern == LLAPI_LAYOUT_DEFAULT, "pattern = %"PRIu64"\n",
382                 pattern);
383
384         llapi_layout_free(layout);
385 }
386
387 /* Verify llapi_layout_patter_set() return values for various inputs. */
388 #define T9_DESC         "verify llapi_layout_pattern_set() return values"
389 void test9(void)
390 {
391         struct llapi_layout *layout;
392         int rc;
393
394         layout = llapi_layout_alloc();
395         ASSERTF(layout != NULL, "errno = %d\n", errno);
396
397         errno = 0;
398         rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_INVALID);
399         ASSERTF(rc == -1 && errno == EOPNOTSUPP, "rc = %d, errno = %d", rc,
400                 errno);
401
402         errno = 0;
403         rc = llapi_layout_pattern_set(NULL, LLAPI_LAYOUT_DEFAULT);
404         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc,
405                 errno);
406
407         errno = 0;
408         rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_DEFAULT);
409         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
410
411         errno = 0;
412         rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_RAID0);
413         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
414
415         llapi_layout_free(layout);
416 }
417
418 /* Verify stripe_count interfaces return errors as expected */
419 #define T10_DESC        "stripe_count error handling"
420 void test10(void)
421 {
422         int rc;
423         uint64_t count;
424         struct llapi_layout *layout;
425
426         layout = llapi_layout_alloc();
427         ASSERTF(layout != NULL, "errno = %d", errno);
428
429         /* invalid stripe count */
430         errno = 0;
431         rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_INVALID);
432         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
433
434         errno = 0;
435         rc = llapi_layout_stripe_count_set(layout, -1);
436         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
437
438         /* NULL layout */
439         errno = 0;
440         rc = llapi_layout_stripe_count_set(NULL, 2);
441         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
442
443         /* NULL layout */
444         errno = 0;
445         rc = llapi_layout_stripe_count_get(NULL, &count);
446         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
447
448         /* NULL count */
449         errno = 0;
450         rc = llapi_layout_stripe_count_get(layout, NULL);
451         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
452
453         /* stripe count too large */
454         errno = 0;
455         rc = llapi_layout_stripe_count_set(layout, LOV_MAX_STRIPE_COUNT + 1);
456         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
457         llapi_layout_free(layout);
458 }
459
460 /* Verify stripe_size interfaces return errors as expected */
461 #define T11_DESC        "stripe_size error handling"
462 void test11(void)
463 {
464         int rc;
465         uint64_t size;
466         struct llapi_layout *layout;
467
468         layout = llapi_layout_alloc();
469         ASSERTF(layout != NULL, "errno = %d", errno);
470
471         /* negative stripe size */
472         errno = 0;
473         rc = llapi_layout_stripe_size_set(layout, -1);
474         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
475
476         /* invalid stripe size */
477         errno = 0;
478         rc = llapi_layout_stripe_size_set(layout, LLAPI_LAYOUT_INVALID);
479         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
480
481         /* stripe size too big */
482         errno = 0;
483         rc = llapi_layout_stripe_size_set(layout, (1ULL << 33));
484         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
485
486         /* NULL layout */
487         errno = 0;
488         rc = llapi_layout_stripe_size_set(NULL, 1048576);
489         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
490
491         errno = 0;
492         rc = llapi_layout_stripe_size_get(NULL, &size);
493         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
494
495         /* NULL size */
496         errno = 0;
497         rc = llapi_layout_stripe_size_get(layout, NULL);
498         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
499
500         llapi_layout_free(layout);
501 }
502
503 /* Verify pool_name interfaces return errors as expected */
504 #define T12_DESC        "pool_name error handling"
505 void test12(void)
506 {
507         int rc;
508         struct llapi_layout *layout;
509         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
510
511         layout = llapi_layout_alloc();
512         ASSERTF(layout != NULL, "errno = %d", errno);
513
514         /* NULL layout */
515         errno = 0;
516         rc = llapi_layout_pool_name_set(NULL, "foo");
517         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
518
519         /* NULL pool name */
520         errno = 0;
521         rc = llapi_layout_pool_name_set(layout, NULL);
522         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
523
524         /* NULL layout */
525         errno = 0;
526         rc = llapi_layout_pool_name_get(NULL, mypool, sizeof(mypool));
527         ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
528
529         /* NULL buffer */
530         errno = 0;
531         rc = llapi_layout_pool_name_get(layout, NULL, sizeof(mypool));
532         ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
533
534         /* Pool name too long*/
535         errno = 0;
536         rc = llapi_layout_pool_name_set(layout, "0123456789abcdef");
537         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
538
539         llapi_layout_free(layout);
540 }
541
542 /* Verify ost_index interface returns errors as expected */
543 #define T13FILE                 "t13"
544 #define T13_STRIPE_COUNT        2
545 #define T13_DESC                "ost_index error handling"
546 void test13(void)
547 {
548         int rc;
549         int fd;
550         uint64_t idx;
551         struct llapi_layout *layout;
552         char path[PATH_MAX];
553
554         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T13FILE);
555
556         layout = llapi_layout_alloc();
557         ASSERTF(layout != NULL, "errno = %d", errno);
558
559         /* invalid OST index */
560         errno = 0;
561         rc = llapi_layout_ost_index_set(layout, 0, LLAPI_LAYOUT_INVALID);
562         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
563
564         errno = 0;
565         rc = llapi_layout_ost_index_set(layout, 0, -1);
566         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
567
568         /* NULL layout */
569         errno = 0;
570         rc = llapi_layout_ost_index_set(NULL, 0, 1);
571         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
572
573         errno = 0;
574         rc = llapi_layout_ost_index_get(NULL, 0, &idx);
575         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
576
577         /* NULL index */
578         errno = 0;
579         rc = llapi_layout_ost_index_get(layout, 0, NULL);
580         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
581
582         /* Layout not read from file so has no OST data. */
583         errno = 0;
584         rc = llapi_layout_stripe_count_set(layout, T13_STRIPE_COUNT);
585         ASSERTF(rc == 0, "errno = %d", errno);
586         rc = llapi_layout_ost_index_get(layout, 0, &idx);
587         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
588
589         /* n greater than stripe count*/
590         rc = unlink(path);
591         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
592         rc = llapi_layout_stripe_count_set(layout, T13_STRIPE_COUNT);
593         ASSERTF(rc == 0, "errno = %d", errno);
594         fd = llapi_layout_file_create(path, 0, 0644, layout);
595         ASSERTF(fd >= 0, "errno = %d", errno);
596         rc = close(fd);
597         ASSERTF(rc == 0, "errno = %d", errno);
598         llapi_layout_free(layout);
599
600         layout = llapi_layout_get_by_path(path, 0);
601         ASSERTF(layout != NULL, "errno = %d", errno);
602         errno = 0;
603         rc = llapi_layout_ost_index_get(layout, T13_STRIPE_COUNT + 1, &idx);
604         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
605
606         llapi_layout_free(layout);
607 }
608
609 /* Verify llapi_layout_file_create() returns errors as expected */
610 #define T14_DESC        "llapi_layout_file_create error handling"
611 void test14(void)
612 {
613         int rc;
614         struct llapi_layout *layout = llapi_layout_alloc();
615
616         /* NULL path */
617         errno = 0;
618         rc = llapi_layout_file_create(NULL, 0, 0, layout);
619         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
620
621         llapi_layout_free(layout);
622 }
623
624 /* Can't change striping attributes of existing file. */
625 #define T15FILE                 "t15"
626 #define T15_STRIPE_COUNT        2
627 #define T15_DESC        "Can't change striping attributes of existing file"
628 void test15(void)
629 {
630         int rc;
631         int fd;
632         uint64_t count;
633         struct llapi_layout *layout;
634         char path[PATH_MAX];
635
636         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T15FILE);
637
638         rc = unlink(path);
639         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
640
641         layout = llapi_layout_alloc();
642         ASSERTF(layout != NULL, "errno = %d", errno);
643         rc = llapi_layout_stripe_count_set(layout, T15_STRIPE_COUNT);
644         ASSERTF(rc == 0, "errno = %d", errno);
645
646         errno = 0;
647         fd = llapi_layout_file_create(path, 0, 0640, layout);
648         ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
649         rc = close(fd);
650         ASSERTF(rc == 0, "errno = %d", errno);
651
652         rc = llapi_layout_stripe_count_set(layout, T15_STRIPE_COUNT - 1);
653         errno = 0;
654         fd = llapi_layout_file_open(path, 0, 0640, layout);
655         ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
656         rc = close(fd);
657         ASSERTF(rc == 0, "errno = %d", errno);
658         llapi_layout_free(layout);
659
660         layout = llapi_layout_get_by_path(path, 0);
661         ASSERTF(layout != NULL, "errno = %d", errno);
662         rc = llapi_layout_stripe_count_get(layout, &count);
663         ASSERTF(rc == 0 && count == T15_STRIPE_COUNT,
664                 "rc = %d, %"PRIu64" != %d", rc, count, T15_STRIPE_COUNT);
665         llapi_layout_free(layout);
666 }
667
668 /* Default stripe attributes are applied as expected. */
669 #define T16FILE         "t16"
670 #define T16_DESC        "Default stripe attributes are applied as expected"
671 void test16(void)
672 {
673         int             rc;
674         int             fd;
675         struct llapi_layout     *deflayout;
676         struct llapi_layout     *filelayout;
677         char            path[PATH_MAX];
678         uint64_t        fsize;
679         uint64_t        fcount;
680         uint64_t        dsize;
681         uint64_t        dcount;
682
683         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T16FILE);
684
685         rc = unlink(path);
686         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
687
688         deflayout = llapi_layout_get_by_path(lustre_dir, LAYOUT_GET_EXPECTED);
689         ASSERTF(deflayout != NULL, "errno = %d", errno);
690         rc = llapi_layout_stripe_size_get(deflayout, &dsize);
691         ASSERTF(rc == 0, "errno = %d", errno);
692         rc = llapi_layout_stripe_count_get(deflayout, &dcount);
693         ASSERTF(rc == 0, "errno = %d", errno);
694
695         /* First, with a default struct llapi_layout */
696         filelayout = llapi_layout_alloc();
697         ASSERTF(filelayout != NULL, "errno = %d", errno);
698
699         fd = llapi_layout_file_create(path, 0, 0640, filelayout);
700         ASSERTF(fd >= 0, "errno = %d", errno);
701
702         rc = close(fd);
703         ASSERTF(rc == 0, "errno = %d", errno);
704
705         llapi_layout_free(filelayout);
706
707         filelayout = llapi_layout_get_by_path(path, 0);
708         ASSERTF(filelayout != NULL, "errno = %d", errno);
709
710         rc = llapi_layout_stripe_count_get(filelayout, &fcount);
711         ASSERTF(rc == 0, "errno = %d", errno);
712         ASSERTF(fcount == dcount, "%"PRIu64" != %"PRIu64, fcount, dcount);
713
714         rc = llapi_layout_stripe_size_get(filelayout, &fsize);
715         ASSERTF(rc == 0, "errno = %d", errno);
716         ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
717
718         /* NULL layout also implies default layout */
719         rc = unlink(path);
720         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
721
722         fd = llapi_layout_file_create(path, 0, 0640, filelayout);
723         ASSERTF(fd >= 0, "errno = %d", errno);
724         rc = close(fd);
725         ASSERTF(rc == 0, "errno = %d", errno);
726         filelayout = llapi_layout_get_by_path(path, 0);
727         ASSERTF(filelayout != NULL, "errno = %d", errno);
728
729         rc = llapi_layout_stripe_count_get(filelayout, &fcount);
730         ASSERTF(rc == 0, "errno = %d", errno);
731         rc = llapi_layout_stripe_size_get(filelayout, &fsize);
732         ASSERTF(rc == 0, "errno = %d", errno);
733         ASSERTF(fcount == dcount, "%"PRIu64" != %"PRIu64, fcount, dcount);
734         ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
735
736         llapi_layout_free(filelayout);
737         llapi_layout_free(deflayout);
738 }
739
740 /* Setting stripe count to LLAPI_LAYOUT_WIDE uses all available OSTs. */
741 #define T17FILE         "t17"
742 #define T17_DESC        "LLAPI_LAYOUT_WIDE is honored"
743 void test17(void)
744 {
745         int rc;
746         int fd;
747         int osts_all;
748         uint64_t osts_layout;
749         struct llapi_layout *layout;
750         char path[PATH_MAX];
751
752         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T17FILE);
753
754         rc = unlink(path);
755         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
756         layout = llapi_layout_alloc();
757         ASSERTF(layout != NULL, "errno = %d", errno);
758         rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_WIDE);
759         ASSERTF(rc == 0, "errno = %d", errno);
760         fd = llapi_layout_file_create(path, 0, 0640, layout);
761         ASSERTF(fd >= 0, "errno = %d", errno);
762         rc = close(fd);
763         ASSERTF(rc == 0, "errno = %d", errno);
764         llapi_layout_free(layout);
765
766         /* Get number of available OSTs */
767         fd = open(path, O_RDONLY);
768         ASSERTF(fd >= 0, "errno = %d", errno);
769         rc = llapi_lov_get_uuids(fd, NULL, &osts_all);
770         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
771         rc = close(fd);
772         ASSERTF(rc == 0, "errno = %d", errno);
773
774         layout = llapi_layout_get_by_path(path, 0);
775         ASSERTF(layout != NULL, "errno = %d", errno);
776         rc = llapi_layout_stripe_count_get(layout, &osts_layout);
777         ASSERTF(osts_layout == osts_all, "%"PRIu64" != %d", osts_layout,
778                 osts_all);
779
780         llapi_layout_free(layout);
781 }
782
783 /* Setting pool with "fsname.pool" notation. */
784 #define T18FILE         "t18"
785 #define T18_DESC        "Setting pool with fsname.pool notation"
786 void test18(void)
787 {
788         int rc;
789         int fd;
790         struct llapi_layout *layout = llapi_layout_alloc();
791         char path[PATH_MAX];
792         char pool[LOV_MAXPOOLNAME*2 + 1];
793         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
794
795         snprintf(pool, sizeof(pool), "lustre.%s", poolname);
796
797         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T18FILE);
798
799         ASSERTF(layout != NULL, "errno = %d", errno);
800
801         rc = unlink(path);
802         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
803
804         rc = llapi_layout_pool_name_set(layout, pool);
805         ASSERTF(rc == 0, "errno = %d", errno);
806
807         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
808         ASSERTF(rc == 0, "errno = %d", errno);
809         rc = strcmp(mypool, poolname);
810         ASSERTF(rc == 0, "%s != %s", mypool, poolname);
811         fd = llapi_layout_file_create(path, 0, 0640, layout);
812         ASSERTF(fd >= 0, "errno = %d", errno);
813         rc = close(fd);
814         ASSERTF(rc == 0, "errno = %d", errno);
815
816         llapi_layout_free(layout);
817
818         layout = llapi_layout_get_by_path(path, 0);
819         ASSERTF(layout != NULL, "errno = %d", errno);
820         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
821         ASSERTF(rc == 0, "errno = %d", errno);
822         rc = strcmp(mypool, poolname);
823         ASSERTF(rc == 0, "%s != %s", mypool, poolname);
824         llapi_layout_free(layout);
825 }
826
827 #define T19_DESC        "Maximum length pool name is NULL-terminated"
828 void test19(void)
829 {
830         struct llapi_layout *layout;
831         char *name = "0123456789abcde";
832         char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
833         int rc;
834
835         layout = llapi_layout_alloc();
836         ASSERTF(layout != NULL, "errno = %d", errno);
837         rc = llapi_layout_pool_name_set(layout, name);
838         ASSERTF(rc == 0, "errno = %d", errno);
839         rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
840         ASSERTF(strlen(name) == strlen(mypool), "name = %s, str = %s", name,
841                 mypool);
842         llapi_layout_free(layout);
843 }
844
845 #define T20FILE         "t20"
846 #define T20_DESC        "LLAPI_LAYOUT_DEFAULT is honored"
847 void test20(void)
848 {
849         int             rc;
850         int             fd;
851         struct llapi_layout     *deflayout;
852         struct llapi_layout     *filelayout;
853         char            path[PATH_MAX];
854         uint64_t        fsize;
855         uint64_t        fcount;
856         uint64_t        dsize;
857         uint64_t        dcount;
858
859         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T20FILE);
860
861         rc = unlink(path);
862         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
863
864         filelayout = llapi_layout_alloc();
865         ASSERTF(filelayout != NULL, "errno = %d", errno);
866
867         rc = llapi_layout_stripe_size_set(filelayout, LLAPI_LAYOUT_DEFAULT);
868         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
869
870         rc = llapi_layout_stripe_count_set(filelayout, LLAPI_LAYOUT_DEFAULT);
871         ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
872
873         fd = llapi_layout_file_create(path, 0, 0640, filelayout);
874         ASSERTF(fd >= 0, "errno = %d", errno);
875
876         rc = close(fd);
877         ASSERTF(rc == 0, "errno = %d", errno);
878
879         llapi_layout_free(filelayout);
880
881         deflayout = llapi_layout_get_by_path(lustre_dir, LAYOUT_GET_EXPECTED);
882         ASSERTF(deflayout != NULL, "errno = %d", errno);
883
884         filelayout = llapi_layout_get_by_path(path, 0);
885         ASSERTF(filelayout != NULL, "errno = %d", errno);
886
887         rc = llapi_layout_stripe_count_get(filelayout, &fcount);
888         ASSERTF(rc == 0, "errno = %d", errno);
889         rc = llapi_layout_stripe_count_get(deflayout, &dcount);
890         ASSERTF(rc == 0, "errno = %d", errno);
891         ASSERTF(fcount == dcount, "%"PRIu64" != %"PRIu64, fcount, dcount);
892
893         rc = llapi_layout_stripe_size_get(filelayout, &fsize);
894         ASSERTF(rc == 0, "errno = %d", errno);
895         rc = llapi_layout_stripe_size_get(deflayout, &dsize);
896         ASSERTF(rc == 0, "errno = %d", errno);
897         ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
898
899         llapi_layout_free(filelayout);
900         llapi_layout_free(deflayout);
901 }
902
903 #define T21_DESC        "llapi_layout_file_create fails for non-Lustre file"
904 void test21(void)
905 {
906         struct llapi_layout *layout;
907         char template[PATH_MAX];
908         int fd;
909         int rc;
910
911         snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
912         fd = mkstemp(template);
913         ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
914         rc = close(fd);
915         ASSERTF(rc == 0, "errno = %d", fd);
916         rc = unlink(template);
917         ASSERTF(rc == 0, "errno = %d", errno);
918
919         layout = llapi_layout_alloc();
920         ASSERTF(layout != NULL, "errno = %d", errno);
921
922         fd = llapi_layout_file_create(template, 0, 0640, layout);
923         ASSERTF(fd == -1 && errno == ENOTTY,
924                 "fd = %d, errno = %d, template = %s", fd, errno, template);
925         llapi_layout_free(layout);
926 }
927
928 #define T22FILE         "t22"
929 #define T22_DESC        "llapi_layout_file_create applied mode correctly"
930 void test22(void)
931 {
932         int             rc;
933         int             fd;
934         char            path[PATH_MAX];
935         struct stat     st;
936         mode_t          mode_in = 0640;
937         mode_t          mode_out;
938         mode_t          umask_orig;
939
940         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T22FILE);
941
942         rc = unlink(path);
943         ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
944
945         umask_orig = umask(S_IWGRP | S_IWOTH);
946
947         fd = llapi_layout_file_create(path, 0, mode_in, NULL);
948         ASSERTF(fd >= 0, "errno = %d", errno);
949
950         (void) umask(umask_orig);
951
952         rc = fstat(fd, &st);
953         ASSERTF(rc == 0, "errno = %d", errno);
954
955         rc = close(fd);
956         ASSERTF(rc == 0, "errno = %d", fd);
957
958         mode_out = st.st_mode & ~S_IFMT;
959         ASSERTF(mode_in == mode_out, "%o != %o", mode_in, mode_out);
960 }
961
962 #define T23_DESC        "llapi_layout_get_by_path fails for non-Lustre file"
963 void test23(void)
964 {
965         struct llapi_layout *layout;
966         char template[PATH_MAX];
967         int fd;
968         int rc;
969
970         snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
971         fd = mkstemp(template);
972         ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
973         rc = close(fd);
974         ASSERTF(rc == 0, "errno = %d", fd);
975
976         layout = llapi_layout_get_by_path(template, 0);
977         ASSERTF(layout == NULL && errno == ENOTTY,
978                 "errno = %d, template = %s", errno, template);
979
980         rc = unlink(template);
981         ASSERTF(rc == 0, "errno = %d", errno);
982 }
983
984 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
985  * for file with unspecified layout. */
986 #define T24FILE         "t24"
987 #define T24_DESC        "LAYOUT_GET_EXPECTED works with existing file"
988 void test24(void)
989 {
990         int fd;
991         int rc;
992         struct llapi_layout *layout;
993         uint64_t count;
994         uint64_t size;
995         uint64_t pattern;
996         char path[PATH_MAX];
997
998         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T24FILE);
999
1000         rc = unlink(path);
1001         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1002         fd = open(path, O_CREAT, 0640);
1003         ASSERTF(fd >= 0, "errno = %d", errno);
1004         rc = close(fd);
1005         ASSERTF(rc == 0, "errno = %d", errno);
1006
1007         layout = llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED);
1008         ASSERTF(layout != NULL, "errno = %d\n", errno);
1009
1010         rc = llapi_layout_stripe_count_get(layout, &count);
1011         ASSERTF(rc == 0, "errno = %d\n", errno);
1012         ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1013
1014         rc = llapi_layout_stripe_size_get(layout, &size);
1015         ASSERTF(rc == 0, "errno = %d\n", errno);
1016         ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1017
1018         rc = llapi_layout_pattern_get(layout, &pattern);
1019         ASSERTF(rc == 0, "errno = %d\n", errno);
1020         ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1021
1022         llapi_layout_free(layout);
1023 }
1024
1025 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
1026  * for directory with unspecified layout. */
1027 #define T25DIR          "d25"
1028 #define T25_DESC        "LAYOUT_GET_EXPECTED works with directory"
1029 void test25(void)
1030 {
1031         int rc;
1032         struct llapi_layout *layout;
1033         uint64_t count;
1034         uint64_t size;
1035         uint64_t pattern;
1036         char dir[PATH_MAX];
1037
1038         snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T25DIR);
1039
1040         rc = rmdir(dir);
1041         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1042         rc = mkdir(dir, 0750);
1043         ASSERTF(rc == 0, "errno = %d", errno);
1044
1045         layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1046         ASSERTF(layout != NULL, "errno = %d\n", errno);
1047
1048         rc = llapi_layout_stripe_count_get(layout, &count);
1049         ASSERTF(rc == 0, "errno = %d\n", errno);
1050         ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1051
1052         rc = llapi_layout_stripe_size_get(layout, &size);
1053         ASSERTF(rc == 0, "errno = %d\n", errno);
1054         ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1055
1056         rc = llapi_layout_pattern_get(layout, &pattern);
1057         ASSERTF(rc == 0, "errno = %d\n", errno);
1058         ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1059
1060         llapi_layout_free(layout);
1061 }
1062
1063 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) correctly combines
1064  * specified attributes of parent directory with attributes filesystem root. */
1065 #define T26DIR          "d26"
1066 #define T26_DESC        "LAYOUT_GET_EXPECTED partially specified parent"
1067 #define T26_STRIPE_SIZE (1048576 * 4)
1068 void test26(void)
1069 {
1070         int rc;
1071         struct llapi_layout *layout;
1072         const char *lfs = getenv("LFS");
1073         uint64_t count;
1074         uint64_t size;
1075         uint64_t pattern;
1076         char dir[PATH_MAX];
1077         char cmd[4096];
1078
1079         snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T26DIR);
1080         rc = rmdir(dir);
1081         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1082         rc = mkdir(dir, 0750);
1083         ASSERTF(rc == 0, "errno = %d", errno);
1084
1085         if (lfs == NULL)
1086                 lfs = "/usr/bin/lfs";
1087
1088         snprintf(cmd, sizeof(cmd), "%s setstripe -s %d %s", lfs,
1089                  T26_STRIPE_SIZE, dir);
1090         rc = system(cmd);
1091         ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1092
1093         layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1094         ASSERTF(layout != NULL, "errno = %d\n", errno);
1095
1096         rc = llapi_layout_stripe_count_get(layout, &count);
1097         ASSERTF(rc == 0, "errno = %d\n", errno);
1098         ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1099
1100         rc = llapi_layout_stripe_size_get(layout, &size);
1101         ASSERTF(rc == 0, "errno = %d\n", errno);
1102         ASSERTF(size == T26_STRIPE_SIZE, "size = %"PRIu64, size);
1103
1104         rc = llapi_layout_pattern_get(layout, &pattern);
1105         ASSERTF(rc == 0, "errno = %d\n", errno);
1106         ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1107
1108         llapi_layout_free(layout);
1109 }
1110
1111 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) work with
1112  * non existing file. */
1113 #define T27DIR          "d27"
1114 #define T27_DESC        "LAYOUT_GET_EXPECTED with non existing file"
1115 #define T27_STRIPE_SIZE (1048576 * 3)
1116 void test27(void)
1117 {
1118         int rc;
1119         struct llapi_layout *layout;
1120         const char *lfs = getenv("LFS");
1121         uint64_t count;
1122         uint64_t size;
1123         uint64_t pattern;
1124         char dirpath[PATH_MAX];
1125         char filepath[PATH_MAX];
1126         char cmd[4096];
1127
1128         snprintf(dirpath, sizeof(dirpath), "%s/%s", lustre_dir, T27DIR);
1129         snprintf(filepath, sizeof(filepath), "%s/nonesuch", dirpath);
1130
1131         rc = rmdir(dirpath);
1132         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1133         rc = mkdir(dirpath, 0750);
1134         ASSERTF(rc == 0, "errno = %d", errno);
1135
1136         if (lfs == NULL)
1137                 lfs = "/usr/bin/lfs";
1138
1139         snprintf(cmd, sizeof(cmd), "%s setstripe -s %d %s", lfs,
1140                  T27_STRIPE_SIZE, dirpath);
1141         rc = system(cmd);
1142         ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1143
1144         layout = llapi_layout_get_by_path(filepath, LAYOUT_GET_EXPECTED);
1145         ASSERTF(layout != NULL, "errno = %d\n", errno);
1146
1147         rc = llapi_layout_stripe_count_get(layout, &count);
1148         ASSERTF(rc == 0, "errno = %d\n", errno);
1149         ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1150
1151         rc = llapi_layout_stripe_size_get(layout, &size);
1152         ASSERTF(rc == 0, "errno = %d\n", errno);
1153         ASSERTF(size == T27_STRIPE_SIZE, "size = %"PRIu64, size);
1154
1155         rc = llapi_layout_pattern_get(layout, &pattern);
1156         ASSERTF(rc == 0, "errno = %d\n", errno);
1157         ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1158
1159         llapi_layout_free(layout);
1160 }
1161
1162 /* llapi_layout_stripe_count_get returns LLAPI_LAYOUT_WIDE for a directory
1163  * with a stripe_count of -1. */
1164 #define T28DIR          "d28"
1165 #define T28_DESC        "LLAPI_LAYOUT_WIDE returned as expected"
1166 void test28(void)
1167 {
1168         int rc;
1169         struct llapi_layout *layout;
1170         const char *lfs = getenv("LFS");
1171         uint64_t count;
1172         char dirpath[PATH_MAX];
1173         char cmd[4096];
1174
1175         snprintf(dirpath, sizeof(dirpath), "%s/%s", lustre_dir, T28DIR);
1176
1177         rc = rmdir(dirpath);
1178         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1179         rc = mkdir(dirpath, 0750);
1180         ASSERTF(rc == 0, "errno = %d", errno);
1181
1182         if (lfs == NULL)
1183                 lfs = "/usr/bin/lfs";
1184
1185         snprintf(cmd, sizeof(cmd), "%s setstripe -c -1 %s", lfs, dirpath);
1186         rc = system(cmd);
1187         ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1188
1189         layout = llapi_layout_get_by_path(dirpath, 0);
1190         ASSERTF(layout != NULL, "errno = %d\n", errno);
1191
1192         rc = llapi_layout_stripe_count_get(layout, &count);
1193         ASSERTF(rc == 0, "errno = %d\n", errno);
1194         ASSERTF(count == LLAPI_LAYOUT_WIDE, "count = %"PRIu64"\n", count);
1195
1196         llapi_layout_free(layout);
1197 }
1198
1199 #define T29FILE         "f29"
1200 #define T29_DESC        "set ost index to non-zero stripe number"
1201 void test29(void)
1202 {
1203         int rc, fd, i;
1204         uint64_t ost0, ost1, nost;
1205         struct llapi_layout *layout;
1206         char path[PATH_MAX];
1207
1208         if (num_osts < 2)
1209                 return;
1210
1211         layout = llapi_layout_alloc();
1212         ASSERTF(layout != NULL, "errno %d", errno);
1213
1214         snprintf(path, sizeof(path), "%s/%s", lustre_dir, T29FILE);
1215
1216         rc = unlink(path);
1217         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1218
1219         /* set ost index to LLAPI_LAYOUT_IDX_MAX should fail */
1220         rc = llapi_layout_ost_index_set(layout, 1, LLAPI_LAYOUT_IDX_MAX);
1221         ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d\n",
1222                 rc, errno);
1223
1224         /* specify ost index partially */
1225         rc = llapi_layout_ost_index_set(layout, 1, 0);
1226         ASSERTF(rc == 0, "errno = %d", errno);
1227
1228         /* create a partially specified layout will fail */
1229         fd = llapi_layout_file_create(path, 0, 0660, layout);
1230         ASSERTF(fd == -1 && errno == EINVAL, "path = %s, fd = %d, errno = %d",
1231                 path, fd, errno);
1232
1233         rc = unlink(path);
1234         ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1235
1236         /* specify all stripes */
1237         rc = llapi_layout_ost_index_set(layout, 0, 1);
1238         ASSERTF(rc == 0, "errno = %d", errno);
1239
1240         /* create */
1241         fd = llapi_layout_file_create(path, 0, 0660, layout);
1242         ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1243
1244         rc = close(fd);
1245         ASSERTF(rc == 0, "errno = %d", errno);
1246         llapi_layout_free(layout);
1247
1248         /* get layout from file */
1249         layout = llapi_layout_get_by_path(path, 0);
1250         ASSERTF(layout != NULL, "errno = %d", errno);
1251
1252         rc = llapi_layout_ost_index_get(layout, 0, &ost0);
1253         ASSERTF(rc == 0, "errno = %d", errno);
1254         rc = llapi_layout_ost_index_get(layout, 1, &ost1);
1255         ASSERTF(rc == 0, "errno = %d", errno);
1256         ASSERTF(ost0 == 1, "%"PRIu64" != %d", ost0, 1);
1257         ASSERTF(ost1 == 0, "%"PRIu64" != %d", ost1, 0);
1258         llapi_layout_free(layout);
1259
1260         /* specify more ost indexes to test realloc */
1261         nost = 0;
1262         layout = llapi_layout_alloc();
1263         ASSERTF(layout != NULL, "errno %d", errno);
1264         for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++) {
1265                 rc = llapi_layout_ost_index_set(layout, i, nost);
1266                 ASSERTF(rc == 0, "errno = %d", errno);
1267                 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1268                 ASSERTF(rc == 0, "errno = %d", errno);
1269                 nost++;
1270                 if (nost == num_osts)
1271                         nost = 0;
1272         }
1273
1274         nost = 0;
1275         for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++) {
1276                 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1277                 ASSERTF(rc == 0, "errno = %d", errno);
1278                 ASSERTF(ost0 == nost, "ost=%"PRIu64" nost=%"PRIu64"",
1279                         ost0, nost);
1280                 nost++;
1281                 if (nost == num_osts)
1282                         nost = 0;
1283         }
1284         llapi_layout_free(layout);
1285
1286         nost = 0;
1287         layout = llapi_layout_alloc();
1288         ASSERTF(layout != NULL, "errno %d", errno);
1289         for (i = LOV_MAX_STRIPE_COUNT-1; i >= 0; i--) {
1290                 rc = llapi_layout_ost_index_set(layout, i, nost);
1291                 ASSERTF(rc == 0, "errno = %d", errno);
1292                 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1293                 ASSERTF(rc == 0, "errno = %d", errno);
1294                 nost++;
1295                 if (nost == num_osts)
1296                         nost = 0;
1297         }
1298
1299         nost = 0;
1300         for (i = LOV_MAX_STRIPE_COUNT-1; i <= 0; i--) {
1301                 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1302                 ASSERTF(rc == 0, "errno = %d", errno);
1303                 ASSERTF(ost0 == nost, "ost=%"PRIu64", nost=%"PRIu64"",
1304                         ost0, nost);
1305                 nost++;
1306                 if (nost == num_osts)
1307                         nost = 0;
1308         }
1309         llapi_layout_free(layout);
1310 }
1311
1312 #define TEST_DESC_LEN   50
1313 struct test_tbl_entry {
1314         void (*tte_fn)(void);
1315         char tte_desc[TEST_DESC_LEN];
1316         bool tte_skip;
1317 };
1318
1319 static struct test_tbl_entry test_tbl[] = {
1320         { &test0,  T0_DESC, false },
1321         { &test1,  T1_DESC, false },
1322         { &test2,  T2_DESC, false },
1323         { &test3,  T3_DESC, false },
1324         { &test4,  T4_DESC, false },
1325         { &test5,  T5_DESC, false },
1326         { &test6,  T6_DESC, false },
1327         { &test7,  T7_DESC, false },
1328         { &test8,  T8_DESC, false },
1329         { &test9,  T9_DESC, false },
1330         { &test10, T10_DESC, false },
1331         { &test11, T11_DESC, false },
1332         { &test12, T12_DESC, false },
1333         { &test13, T13_DESC, false },
1334         { &test14, T14_DESC, false },
1335         { &test15, T15_DESC, false },
1336         { &test16, T16_DESC, false },
1337         { &test17, T17_DESC, false },
1338         { &test18, T18_DESC, false },
1339         { &test19, T19_DESC, false },
1340         { &test20, T20_DESC, false },
1341         { &test21, T21_DESC, false },
1342         { &test22, T22_DESC, false },
1343         { &test23, T23_DESC, false },
1344         { &test24, T24_DESC, false },
1345         { &test25, T25_DESC, false },
1346         { &test26, T26_DESC, false },
1347         { &test27, T27_DESC, false },
1348         { &test28, T28_DESC, false },
1349         { &test29, T29_DESC, false },
1350 };
1351 #define NUM_TESTS       (sizeof(test_tbl) / sizeof(struct test_tbl_entry))
1352
1353 void print_test_desc(int test_num, const char *test_desc, const char *status)
1354 {
1355         int i;
1356
1357         printf(" test %2d: %s ", test_num, test_desc);
1358         for (i = 0; i < TEST_DESC_LEN - strlen(test_desc); i++)
1359                 printf(".");
1360         printf(" %s\n", status);
1361 }
1362
1363 /* This function runs a single test by forking the process.  This way,
1364  * if there is a segfault during a test, the test program won't crash. */
1365 int test(void (*test_fn)(), const char *test_desc, bool test_skip, int test_num)
1366 {
1367         int rc = 0;
1368         pid_t pid;
1369         char status_buf[128];
1370
1371         if (test_skip) {
1372                 print_test_desc(test_num, test_desc, "skip");
1373                 return 0;
1374         }
1375
1376         pid = fork();
1377         if (pid < 0) {
1378                 ERROR("cannot fork: %s", strerror(errno));
1379         } else if (pid > 0) {
1380                 int status = 0;
1381
1382                 /* Non-zero value indicates failure. */
1383                 wait(&status);
1384                 if (status == 0) {
1385                         strncpy(status_buf, "pass", sizeof(status_buf));
1386                 } else if WIFSIGNALED(status) {
1387                         snprintf(status_buf, sizeof(status_buf),
1388                                  "fail (exit status %d, killed by SIG%d)",
1389                                  WEXITSTATUS(status), WTERMSIG(status));
1390                         rc = -1;
1391                 } else {
1392                         snprintf(status_buf, sizeof(status_buf),
1393                                  "fail (exit status %d)", WEXITSTATUS(status));
1394                         rc = -1;
1395                 }
1396                 print_test_desc(test_num, test_desc, status_buf);
1397         } else if (pid == 0) {
1398                 /* Run the test in the child process.  Exit with 0 for success,
1399                  * non-zero for failure */
1400                 test_fn();
1401                 exit(0);
1402         }
1403
1404         return rc;
1405 }
1406
1407 /* 'str_tests' are the tests to be skipped, such as "1,3,4,.." */
1408 static void set_tests_skipped(char *str_tests)
1409 {
1410         char *ptr = str_tests;
1411         int tstno;
1412
1413         if (ptr == NULL || strlen(ptr) == 0)
1414                 return;
1415
1416         while (*ptr != '\0') {
1417                 tstno = strtoul(ptr, &ptr, 0);
1418                 if (tstno >= 0 && tstno < NUM_TESTS)
1419                         test_tbl[tstno].tte_skip = true;
1420                 if (*ptr == ',')
1421                         ptr++;
1422                 else
1423                         break;
1424         }
1425 }
1426
1427 static void process_args(int argc, char *argv[])
1428 {
1429         int c;
1430
1431         while ((c = getopt(argc, argv, "d:p:o:s:")) != -1) {
1432                 switch (c) {
1433                 case 'd':
1434                         lustre_dir = optarg;
1435                         break;
1436                 case 'p':
1437                         poolname = optarg;
1438                         break;
1439                 case 'o':
1440                         num_osts = atoi(optarg);
1441                         break;
1442                 case 's':
1443                         set_tests_skipped(optarg);
1444                         break;
1445                 case '?':
1446                         fprintf(stderr, "Unknown option '%c'\n", optopt);
1447                         usage(argv[0]);
1448                 }
1449         }
1450 }
1451
1452 int main(int argc, char *argv[])
1453 {
1454         int rc = 0;
1455         int i;
1456         struct stat s;
1457         char fsname[8 + 1];
1458
1459         llapi_msg_set_level(LLAPI_MSG_OFF);
1460
1461         process_args(argc, argv);
1462         if (lustre_dir == NULL)
1463                 lustre_dir = "/mnt/lustre";
1464         if (poolname == NULL)
1465                 poolname = "testpool";
1466         if (num_osts == -1)
1467                 num_osts = 2;
1468
1469         if (num_osts < 2)
1470                 DIE("Error: at least 2 OSTS are required\n");
1471
1472         if (stat(lustre_dir, &s) < 0)
1473                 DIE("cannot stat %s: %s\n", lustre_dir, strerror(errno));
1474         else if (!S_ISDIR(s.st_mode))
1475                 DIE("%s: not a directory\n", lustre_dir);
1476
1477         rc = llapi_search_fsname(lustre_dir, fsname);
1478         if (rc != 0) {
1479                 fprintf(stderr, "Error: %s: not a Lustre filesystem\n",
1480                         lustre_dir);
1481                 exit(EXIT_FAILURE);
1482         }
1483
1484         /* Play nice with Lustre test scripts. Non-line buffered output
1485          * stream under I/O redirection may appear incorrectly. */
1486         setvbuf(stdout, NULL, _IOLBF, 0);
1487
1488         for (i = 0; i < NUM_TESTS; i++) {
1489                 struct test_tbl_entry *tst = &test_tbl[i];
1490                 if (test(tst->tte_fn, tst->tte_desc, tst->tte_skip, i) != 0)
1491                         rc++;
1492         }
1493         return rc;
1494 }