4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
23 * Copyright (c) 2016, 2017, Intel Corporation.
26 * These tests exercise the llapi_layout API which abstracts the layout
27 * of a Lustre file behind an opaque data type. They assume a Lustre
28 * file system with at least 2 OSTs and a pool containing at least the
29 * first 2 OSTs. For example,
31 * sudo lctl pool_new lustre.testpool
32 * sudo lctl pool_add lustre.testpool OST[0-1]
33 * gcc -Wall -g -Werror -o llapi_layout_test llapi_layout_test.c -llustreapi
34 * sudo ./llapi_layout_test
43 #include <sys/signal.h>
44 #include <sys/types.h>
46 #include <lustre/lustreapi.h>
52 #include <sys/ioctl.h>
54 #define ERROR(fmt, ...) \
55 fprintf(stderr, "%s: %s:%d: %s: " fmt "\n", \
56 program_invocation_short_name, __FILE__, __LINE__, \
57 __func__, ## __VA_ARGS__);
59 #define DIE(fmt, ...) \
61 ERROR(fmt, ## __VA_ARGS__); \
65 #define ASSERTF(cond, fmt, ...) \
68 DIE("assertion '%s' failed: "fmt, #cond, ## __VA_ARGS__);\
71 static char *lustre_dir;
72 static char *poolname;
73 static int num_osts = -1;
75 void usage(char *prog)
77 printf("Usage: %s [-d lustre_dir] [-p pool_name] [-o num_osts] "
78 "[-s $n,$m,..]\n", prog);
83 #define T0_STRIPE_COUNT num_osts
84 #define T0_STRIPE_SIZE 1048576
85 #define T0_OST_OFFSET (num_osts - 1)
86 #define T0_DESC "Read/write layout attributes then create a file"
93 struct llapi_layout *layout = llapi_layout_alloc();
95 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
97 ASSERTF(layout != NULL, "errno %d", errno);
99 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
102 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
105 rc = llapi_layout_stripe_count_set(layout, T0_STRIPE_COUNT);
106 ASSERTF(rc == 0, "errno = %d", errno);
107 rc = llapi_layout_stripe_count_get(layout, &count);
108 ASSERTF(rc == 0 && count == T0_STRIPE_COUNT, "%"PRIu64" != %d", count,
112 rc = llapi_layout_stripe_size_set(layout, T0_STRIPE_SIZE);
113 ASSERTF(rc == 0, "errno = %d", errno);
114 rc = llapi_layout_stripe_size_get(layout, &size);
115 ASSERTF(rc == 0 && size == T0_STRIPE_SIZE, "%"PRIu64" != %d", size,
119 rc = llapi_layout_pool_name_set(layout, poolname);
120 ASSERTF(rc == 0, "errno = %d", errno);
121 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
122 ASSERTF(rc == 0, "errno = %d", errno);
123 rc = strcmp(mypool, poolname);
124 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
127 rc = llapi_layout_ost_index_set(layout, 0, T0_OST_OFFSET);
128 ASSERTF(rc == 0, "errno = %d", errno);
131 fd = llapi_layout_file_create(path, 0, 0660, layout);
132 ASSERTF(fd >= 0, "path = %s, errno = %d", path, errno);
134 ASSERTF(rc == 0, "errno = %d", errno);
135 llapi_layout_free(layout);
138 void __test1_helper(struct llapi_layout *layout)
145 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
147 rc = llapi_layout_stripe_count_get(layout, &count);
148 ASSERTF(count == T0_STRIPE_COUNT, "%"PRIu64" != %d", count,
151 rc = llapi_layout_stripe_size_get(layout, &size);
152 ASSERTF(size == T0_STRIPE_SIZE, "%"PRIu64" != %d", size,
155 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
156 ASSERTF(rc == 0, "errno = %d", errno);
157 rc = strcmp(mypool, poolname);
158 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
160 rc = llapi_layout_ost_index_get(layout, 0, &ost0);
161 ASSERTF(rc == 0, "errno = %d", errno);
162 rc = llapi_layout_ost_index_get(layout, 1, &ost1);
163 ASSERTF(rc == 0, "errno = %d", errno);
164 ASSERTF(ost0 == T0_OST_OFFSET, "%"PRIu64" != %d", ost0, T0_OST_OFFSET);
165 ASSERTF(ost1 != ost0, "%"PRIu64" == %"PRIu64, ost0, ost1);
168 #define T1_DESC "Read test0 file by path and verify attributes"
173 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
174 struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
175 ASSERTF(layout != NULL, "errno = %d", errno);
176 __test1_helper(layout);
177 llapi_layout_free(layout);
180 #define T2_DESC "Read test0 file by FD and verify attributes"
187 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
189 fd = open(path, O_RDONLY);
190 ASSERTF(fd >= 0, "open(%s): errno = %d", path, errno);
192 struct llapi_layout *layout = llapi_layout_get_by_fd(fd, 0);
193 ASSERTF(layout != NULL, "errno = %d", errno);
196 ASSERTF(rc == 0, "close(%s): errno = %d", path, errno);
198 __test1_helper(layout);
199 llapi_layout_free(layout);
202 #define T3_DESC "Read test0 file by FID and verify attributes"
206 struct llapi_layout *layout;
211 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
213 rc = llapi_path2fid(path, &fid);
214 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
215 snprintf(fidstr, sizeof(fidstr), "0x%"PRIx64":0x%x:0x%x",
216 (uint64_t)fid.f_seq, fid.f_oid, fid.f_ver);
218 layout = llapi_layout_get_by_fid(path, &fid, 0);
219 ASSERTF(layout != NULL, "fidstr = %s, errno = %d", fidstr, errno);
221 __test1_helper(layout);
222 llapi_layout_free(layout);
226 #define T4_STRIPE_COUNT 2
227 #define T4_STRIPE_SIZE 2097152
228 #define T4_DESC "Verify compatibility with 'lfs setstripe'"
236 const char *lfs = getenv("LFS");
237 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
238 char cmd[PATH_MAX + 128];
241 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T4FILE);
244 lfs = "/usr/bin/lfs";
247 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
249 snprintf(cmd, sizeof(cmd), "%s setstripe %s %s -c %d -S %d %s", lfs,
250 strlen(poolname) > 0 ? "-p" : "", poolname, T4_STRIPE_COUNT,
251 T4_STRIPE_SIZE, path);
253 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
256 struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
257 ASSERTF(layout != NULL, "errno = %d", errno);
259 rc = llapi_layout_stripe_count_get(layout, &count);
260 ASSERTF(count == T4_STRIPE_COUNT, "%"PRIu64" != %d", count,
263 rc = llapi_layout_stripe_size_get(layout, &size);
264 ASSERTF(size == T4_STRIPE_SIZE, "%"PRIu64" != %d", size,
267 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
268 ASSERTF(rc == 0, "errno = %d", errno);
269 rc = strcmp(mypool, poolname);
270 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
272 rc = llapi_layout_ost_index_get(layout, 0, &ost0);
273 ASSERTF(rc == 0, "errno = %d", errno);
274 rc = llapi_layout_ost_index_get(layout, 1, &ost1);
275 ASSERTF(rc == 0, "errno = %d", errno);
276 ASSERTF(ost1 != ost0, "%"PRIu64" == %"PRIu64, ost0, ost1);
278 llapi_layout_free(layout);
282 #define T5_DESC "llapi_layout_get_by_path ENOENT handling"
287 struct llapi_layout *layout;
289 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T5FILE);
292 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
295 layout = llapi_layout_get_by_path(path, 0);
296 ASSERTF(layout == NULL && errno == ENOENT, "errno = %d", errno);
299 #define T6_DESC "llapi_layout_get_by_fd EBADF handling"
303 struct llapi_layout *layout = llapi_layout_get_by_fd(9999, 0);
304 ASSERTF(layout == NULL && errno == EBADF, "errno = %d", errno);
308 #define T7_DESC "llapi_layout_get_by_path EACCES handling"
313 uid_t myuid = getuid();
315 const char *runas = getenv("RUNAS_ID");
319 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T7FILE);
320 ASSERTF(myuid == 0, "myuid = %d", myuid); /* Need root for this test. */
322 /* Create file as root */
324 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
326 fd = open(path, O_CREAT, 0400);
327 ASSERTF(fd > 0, "errno = %d", errno);
329 ASSERTF(rc == 0, "errno = %d", errno);
331 /* Become unprivileged user */
334 ASSERTF(uid != 0, "runas = %s", runas);
336 pw = getpwnam("nobody");
337 ASSERTF(pw != NULL, "errno = %d", errno);
341 ASSERTF(rc == 0, "errno = %d", errno);
343 struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
344 ASSERTF(layout == NULL && errno == EACCES, "errno = %d", errno);
346 ASSERTF(rc == 0, "errno = %d", errno);
349 /* llapi_layout_get_by_path() returns default layout for file with no
350 * striping attributes. */
352 #define T8_DESC "llapi_layout_get_by_path ENODATA handling"
357 struct llapi_layout *layout;
363 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T8FILE);
366 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
367 fd = open(path, O_CREAT, 0640);
368 ASSERTF(fd >= 0, "errno = %d", errno);
370 ASSERTF(rc == 0, "errno = %d", errno);
372 layout = llapi_layout_get_by_path(path, 0);
373 ASSERTF(layout != NULL, "errno = %d\n", errno);
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);
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);
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",
388 llapi_layout_free(layout);
391 /* Verify llapi_layout_patter_set() return values for various inputs. */
392 #define T9_DESC "verify llapi_layout_pattern_set() return values"
395 struct llapi_layout *layout;
398 layout = llapi_layout_alloc();
399 ASSERTF(layout != NULL, "errno = %d\n", errno);
402 rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_INVALID);
403 ASSERTF(rc == -1 && errno == EOPNOTSUPP, "rc = %d, errno = %d", rc,
407 rc = llapi_layout_pattern_set(NULL, LLAPI_LAYOUT_DEFAULT);
408 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc,
412 rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_DEFAULT);
413 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
416 rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_RAID0);
417 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
419 llapi_layout_free(layout);
422 /* Verify stripe_count interfaces return errors as expected */
423 #define T10_DESC "stripe_count error handling"
428 struct llapi_layout *layout;
430 layout = llapi_layout_alloc();
431 ASSERTF(layout != NULL, "errno = %d", errno);
433 /* invalid stripe count */
435 rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_INVALID);
436 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
439 rc = llapi_layout_stripe_count_set(layout, -1);
440 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
444 rc = llapi_layout_stripe_count_set(NULL, 2);
445 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
449 rc = llapi_layout_stripe_count_get(NULL, &count);
450 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
454 rc = llapi_layout_stripe_count_get(layout, NULL);
455 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
457 /* stripe count too large */
459 rc = llapi_layout_stripe_count_set(layout, LOV_MAX_STRIPE_COUNT + 1);
460 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
461 llapi_layout_free(layout);
464 /* Verify stripe_size interfaces return errors as expected */
465 #define T11_DESC "stripe_size error handling"
470 struct llapi_layout *layout;
472 layout = llapi_layout_alloc();
473 ASSERTF(layout != NULL, "errno = %d", errno);
475 /* negative stripe size */
477 rc = llapi_layout_stripe_size_set(layout, -1);
478 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
480 /* invalid stripe size */
482 rc = llapi_layout_stripe_size_set(layout, LLAPI_LAYOUT_INVALID);
483 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
485 /* stripe size too big */
487 rc = llapi_layout_stripe_size_set(layout, (1ULL << 33));
488 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
492 rc = llapi_layout_stripe_size_set(NULL, 1048576);
493 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
496 rc = llapi_layout_stripe_size_get(NULL, &size);
497 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
501 rc = llapi_layout_stripe_size_get(layout, NULL);
502 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
504 llapi_layout_free(layout);
507 /* Verify pool_name interfaces return errors as expected */
508 #define T12_DESC "pool_name error handling"
512 struct llapi_layout *layout;
513 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
515 layout = llapi_layout_alloc();
516 ASSERTF(layout != NULL, "errno = %d", errno);
520 rc = llapi_layout_pool_name_set(NULL, "foo");
521 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
525 rc = llapi_layout_pool_name_set(layout, NULL);
526 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
530 rc = llapi_layout_pool_name_get(NULL, mypool, sizeof(mypool));
531 ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
535 rc = llapi_layout_pool_name_get(layout, NULL, sizeof(mypool));
536 ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
538 /* Pool name too long*/
540 rc = llapi_layout_pool_name_set(layout, "0123456789abcdef");
541 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
543 llapi_layout_free(layout);
546 /* Verify ost_index interface returns errors as expected */
547 #define T13FILE "t13"
548 #define T13_STRIPE_COUNT 2
549 #define T13_DESC "ost_index error handling"
555 struct llapi_layout *layout;
558 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T13FILE);
560 layout = llapi_layout_alloc();
561 ASSERTF(layout != NULL, "errno = %d", errno);
563 /* invalid OST index */
565 rc = llapi_layout_ost_index_set(layout, 0, LLAPI_LAYOUT_INVALID);
566 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
569 rc = llapi_layout_ost_index_set(layout, 0, -1);
570 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
574 rc = llapi_layout_ost_index_set(NULL, 0, 1);
575 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
578 rc = llapi_layout_ost_index_get(NULL, 0, &idx);
579 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
583 rc = llapi_layout_ost_index_get(layout, 0, NULL);
584 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
586 /* Layout not read from file so has no OST data. */
588 rc = llapi_layout_stripe_count_set(layout, T13_STRIPE_COUNT);
589 ASSERTF(rc == 0, "errno = %d", errno);
590 rc = llapi_layout_ost_index_get(layout, 0, &idx);
591 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
593 /* n greater than stripe count*/
595 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
596 rc = llapi_layout_stripe_count_set(layout, T13_STRIPE_COUNT);
597 ASSERTF(rc == 0, "errno = %d", errno);
598 fd = llapi_layout_file_create(path, 0, 0644, layout);
599 ASSERTF(fd >= 0, "errno = %d", errno);
601 ASSERTF(rc == 0, "errno = %d", errno);
602 llapi_layout_free(layout);
604 layout = llapi_layout_get_by_path(path, 0);
605 ASSERTF(layout != NULL, "errno = %d", errno);
607 rc = llapi_layout_ost_index_get(layout, T13_STRIPE_COUNT + 1, &idx);
608 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
610 llapi_layout_free(layout);
613 /* Verify llapi_layout_file_create() returns errors as expected */
614 #define T14_DESC "llapi_layout_file_create error handling"
618 struct llapi_layout *layout = llapi_layout_alloc();
622 rc = llapi_layout_file_create(NULL, 0, 0, layout);
623 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
625 llapi_layout_free(layout);
628 /* Can't change striping attributes of existing file. */
629 #define T15FILE "t15"
630 #define T15_STRIPE_COUNT 2
631 #define T15_DESC "Can't change striping attributes of existing file"
637 struct llapi_layout *layout;
640 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T15FILE);
643 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
645 layout = llapi_layout_alloc();
646 ASSERTF(layout != NULL, "errno = %d", errno);
647 rc = llapi_layout_stripe_count_set(layout, T15_STRIPE_COUNT);
648 ASSERTF(rc == 0, "errno = %d", errno);
651 fd = llapi_layout_file_create(path, 0, 0640, layout);
652 ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
654 ASSERTF(rc == 0, "errno = %d", errno);
656 rc = llapi_layout_stripe_count_set(layout, T15_STRIPE_COUNT - 1);
658 fd = llapi_layout_file_open(path, 0, 0640, layout);
659 ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
661 ASSERTF(rc == 0, "errno = %d", errno);
662 llapi_layout_free(layout);
664 layout = llapi_layout_get_by_path(path, 0);
665 ASSERTF(layout != NULL, "errno = %d", errno);
666 rc = llapi_layout_stripe_count_get(layout, &count);
667 ASSERTF(rc == 0 && count == T15_STRIPE_COUNT,
668 "rc = %d, %"PRIu64" != %d", rc, count, T15_STRIPE_COUNT);
669 llapi_layout_free(layout);
672 /* Default stripe attributes are applied as expected. */
673 #define T16FILE "t16"
674 #define T16_DESC "Default stripe attributes are applied as expected"
679 struct llapi_layout *deflayout;
680 struct llapi_layout *filelayout;
687 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T16FILE);
690 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
692 deflayout = llapi_layout_get_by_path(lustre_dir, LAYOUT_GET_EXPECTED);
693 ASSERTF(deflayout != NULL, "errno = %d", errno);
694 rc = llapi_layout_stripe_size_get(deflayout, &dsize);
695 ASSERTF(rc == 0, "errno = %d", errno);
696 rc = llapi_layout_stripe_count_get(deflayout, &dcount);
697 ASSERTF(rc == 0, "errno = %d", errno);
699 /* First, with a default struct llapi_layout */
700 filelayout = llapi_layout_alloc();
701 ASSERTF(filelayout != NULL, "errno = %d", errno);
703 fd = llapi_layout_file_create(path, 0, 0640, filelayout);
704 ASSERTF(fd >= 0, "errno = %d", errno);
707 ASSERTF(rc == 0, "errno = %d", errno);
709 llapi_layout_free(filelayout);
711 filelayout = llapi_layout_get_by_path(path, 0);
712 ASSERTF(filelayout != NULL, "errno = %d", errno);
714 rc = llapi_layout_stripe_count_get(filelayout, &fcount);
715 ASSERTF(rc == 0, "errno = %d", errno);
716 ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
717 dcount == LLAPI_LAYOUT_WIDE,
718 "%"PRIu64" != %"PRIu64, fcount, dcount);
720 rc = llapi_layout_stripe_size_get(filelayout, &fsize);
721 ASSERTF(rc == 0, "errno = %d", errno);
722 ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
724 /* NULL layout also implies default layout */
726 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
728 fd = llapi_layout_file_create(path, 0, 0640, filelayout);
729 ASSERTF(fd >= 0, "errno = %d", errno);
731 ASSERTF(rc == 0, "errno = %d", errno);
732 filelayout = llapi_layout_get_by_path(path, 0);
733 ASSERTF(filelayout != NULL, "errno = %d", errno);
735 rc = llapi_layout_stripe_count_get(filelayout, &fcount);
736 ASSERTF(rc == 0, "errno = %d", errno);
737 rc = llapi_layout_stripe_size_get(filelayout, &fsize);
738 ASSERTF(rc == 0, "errno = %d", errno);
739 ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
740 dcount == LLAPI_LAYOUT_WIDE,
741 "%"PRIu64" != %"PRIu64, fcount, dcount);
742 ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
744 llapi_layout_free(filelayout);
745 llapi_layout_free(deflayout);
748 /* Setting stripe count to LLAPI_LAYOUT_WIDE uses all available OSTs. */
749 #define T17FILE "t17"
750 #define T17_DESC "LLAPI_LAYOUT_WIDE is honored"
756 uint64_t osts_layout;
757 struct llapi_layout *layout;
760 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T17FILE);
763 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
764 layout = llapi_layout_alloc();
765 ASSERTF(layout != NULL, "errno = %d", errno);
766 rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_WIDE);
767 ASSERTF(rc == 0, "errno = %d", errno);
768 fd = llapi_layout_file_create(path, 0, 0640, layout);
769 ASSERTF(fd >= 0, "errno = %d", errno);
771 ASSERTF(rc == 0, "errno = %d", errno);
772 llapi_layout_free(layout);
774 /* Get number of available OSTs */
775 fd = open(path, O_RDONLY);
776 ASSERTF(fd >= 0, "errno = %d", errno);
777 rc = llapi_lov_get_uuids(fd, NULL, &osts_all);
778 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
780 ASSERTF(rc == 0, "errno = %d", errno);
782 layout = llapi_layout_get_by_path(path, 0);
783 ASSERTF(layout != NULL, "errno = %d", errno);
784 rc = llapi_layout_stripe_count_get(layout, &osts_layout);
785 ASSERTF(osts_layout == osts_all, "%"PRIu64" != %d", osts_layout,
788 llapi_layout_free(layout);
791 /* Setting pool with "fsname.pool" notation. */
792 #define T18FILE "t18"
793 #define T18_DESC "Setting pool with fsname.pool notation"
798 struct llapi_layout *layout = llapi_layout_alloc();
800 char pool[LOV_MAXPOOLNAME*2 + 1];
801 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
803 snprintf(pool, sizeof(pool), "lustre.%s", poolname);
805 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T18FILE);
807 ASSERTF(layout != NULL, "errno = %d", errno);
810 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
812 rc = llapi_layout_pool_name_set(layout, pool);
813 ASSERTF(rc == 0, "errno = %d", errno);
815 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
816 ASSERTF(rc == 0, "errno = %d", errno);
817 rc = strcmp(mypool, poolname);
818 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
819 fd = llapi_layout_file_create(path, 0, 0640, layout);
820 ASSERTF(fd >= 0, "errno = %d", errno);
822 ASSERTF(rc == 0, "errno = %d", errno);
824 llapi_layout_free(layout);
826 layout = llapi_layout_get_by_path(path, 0);
827 ASSERTF(layout != NULL, "errno = %d", errno);
828 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
829 ASSERTF(rc == 0, "errno = %d", errno);
830 rc = strcmp(mypool, poolname);
831 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
832 llapi_layout_free(layout);
835 #define T19_DESC "Maximum length pool name is NULL-terminated"
838 struct llapi_layout *layout;
839 char *name = "0123456789abcde";
840 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
843 layout = llapi_layout_alloc();
844 ASSERTF(layout != NULL, "errno = %d", errno);
845 rc = llapi_layout_pool_name_set(layout, name);
846 ASSERTF(rc == 0, "errno = %d", errno);
847 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
848 ASSERTF(strlen(name) == strlen(mypool), "name = %s, str = %s", name,
850 llapi_layout_free(layout);
853 #define T20FILE "t20"
854 #define T20_DESC "LLAPI_LAYOUT_DEFAULT is honored"
859 struct llapi_layout *deflayout;
860 struct llapi_layout *filelayout;
867 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T20FILE);
870 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
872 filelayout = llapi_layout_alloc();
873 ASSERTF(filelayout != NULL, "errno = %d", errno);
875 rc = llapi_layout_stripe_size_set(filelayout, LLAPI_LAYOUT_DEFAULT);
876 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
878 rc = llapi_layout_stripe_count_set(filelayout, LLAPI_LAYOUT_DEFAULT);
879 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
881 fd = llapi_layout_file_create(path, 0, 0640, filelayout);
882 ASSERTF(fd >= 0, "errno = %d", errno);
885 ASSERTF(rc == 0, "errno = %d", errno);
887 llapi_layout_free(filelayout);
889 deflayout = llapi_layout_get_by_path(lustre_dir, LAYOUT_GET_EXPECTED);
890 ASSERTF(deflayout != NULL, "errno = %d", errno);
892 filelayout = llapi_layout_get_by_path(path, 0);
893 ASSERTF(filelayout != NULL, "errno = %d", errno);
895 rc = llapi_layout_stripe_count_get(filelayout, &fcount);
896 ASSERTF(rc == 0, "errno = %d", errno);
897 rc = llapi_layout_stripe_count_get(deflayout, &dcount);
898 ASSERTF(rc == 0, "errno = %d", errno);
899 ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
900 dcount == LLAPI_LAYOUT_WIDE,
901 "%"PRIu64" != %"PRIu64, fcount, dcount);
903 rc = llapi_layout_stripe_size_get(filelayout, &fsize);
904 ASSERTF(rc == 0, "errno = %d", errno);
905 rc = llapi_layout_stripe_size_get(deflayout, &dsize);
906 ASSERTF(rc == 0, "errno = %d", errno);
907 ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
909 llapi_layout_free(filelayout);
910 llapi_layout_free(deflayout);
913 #define T21_DESC "llapi_layout_file_create fails for non-Lustre file"
916 struct llapi_layout *layout;
917 char template[PATH_MAX];
921 snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
922 fd = mkstemp(template);
923 ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
925 ASSERTF(rc == 0, "errno = %d", fd);
926 rc = unlink(template);
927 ASSERTF(rc == 0, "errno = %d", errno);
929 layout = llapi_layout_alloc();
930 ASSERTF(layout != NULL, "errno = %d", errno);
932 fd = llapi_layout_file_create(template, 0, 0640, layout);
933 ASSERTF(fd == -1 && errno == ENOTTY,
934 "fd = %d, errno = %d, template = %s", fd, errno, template);
935 llapi_layout_free(layout);
938 #define T22FILE "t22"
939 #define T22_DESC "llapi_layout_file_create applied mode correctly"
946 mode_t mode_in = 0640;
950 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T22FILE);
953 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
955 umask_orig = umask(S_IWGRP | S_IWOTH);
957 fd = llapi_layout_file_create(path, 0, mode_in, NULL);
958 ASSERTF(fd >= 0, "errno = %d", errno);
960 (void) umask(umask_orig);
963 ASSERTF(rc == 0, "errno = %d", errno);
966 ASSERTF(rc == 0, "errno = %d", fd);
968 mode_out = st.st_mode & ~S_IFMT;
969 ASSERTF(mode_in == mode_out, "%o != %o", mode_in, mode_out);
972 #define T23_DESC "llapi_layout_get_by_path fails for non-Lustre file"
975 struct llapi_layout *layout;
976 char template[PATH_MAX];
980 snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
981 fd = mkstemp(template);
982 ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
984 ASSERTF(rc == 0, "errno = %d", fd);
986 layout = llapi_layout_get_by_path(template, 0);
987 ASSERTF(layout == NULL && errno == ENOTTY,
988 "errno = %d, template = %s", errno, template);
990 rc = unlink(template);
991 ASSERTF(rc == 0, "errno = %d", errno);
994 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
995 * for file with unspecified layout. */
996 #define T24FILE "t24"
997 #define T24_DESC "LAYOUT_GET_EXPECTED works with existing file"
1002 struct llapi_layout *layout;
1006 char path[PATH_MAX];
1008 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T24FILE);
1011 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1012 fd = open(path, O_CREAT, 0640);
1013 ASSERTF(fd >= 0, "errno = %d", errno);
1015 ASSERTF(rc == 0, "errno = %d", errno);
1017 layout = llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED);
1018 ASSERTF(layout != NULL, "errno = %d\n", errno);
1020 rc = llapi_layout_stripe_count_get(layout, &count);
1021 ASSERTF(rc == 0, "errno = %d\n", errno);
1022 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1024 rc = llapi_layout_stripe_size_get(layout, &size);
1025 ASSERTF(rc == 0, "errno = %d\n", errno);
1026 ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1028 rc = llapi_layout_pattern_get(layout, &pattern);
1029 ASSERTF(rc == 0, "errno = %d\n", errno);
1030 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1032 llapi_layout_free(layout);
1035 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
1036 * for directory with unspecified layout. */
1037 #define T25DIR "d25"
1038 #define T25_DESC "LAYOUT_GET_EXPECTED works with directory"
1042 struct llapi_layout *layout;
1048 snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T25DIR);
1051 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1052 rc = mkdir(dir, 0750);
1053 ASSERTF(rc == 0, "errno = %d", errno);
1055 layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1056 ASSERTF(layout != NULL, "errno = %d\n", errno);
1058 rc = llapi_layout_stripe_count_get(layout, &count);
1059 ASSERTF(rc == 0, "errno = %d\n", errno);
1060 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1062 rc = llapi_layout_stripe_size_get(layout, &size);
1063 ASSERTF(rc == 0, "errno = %d\n", errno);
1064 ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1066 rc = llapi_layout_pattern_get(layout, &pattern);
1067 ASSERTF(rc == 0, "errno = %d\n", errno);
1068 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1070 llapi_layout_free(layout);
1073 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) correctly combines
1074 * specified attributes of parent directory with attributes filesystem root. */
1075 #define T26DIR "d26"
1076 #define T26_DESC "LAYOUT_GET_EXPECTED partially specified parent"
1077 #define T26_STRIPE_SIZE (1048576 * 4)
1081 struct llapi_layout *layout;
1082 const char *lfs = getenv("LFS");
1087 char cmd[PATH_MAX + 64];
1089 snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T26DIR);
1091 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1092 rc = mkdir(dir, 0750);
1093 ASSERTF(rc == 0, "errno = %d", errno);
1096 lfs = "/usr/bin/lfs";
1098 snprintf(cmd, sizeof(cmd), "%s setstripe -S %d %s", lfs,
1099 T26_STRIPE_SIZE, dir);
1101 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1103 layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1104 ASSERTF(layout != NULL, "errno = %d\n", errno);
1106 rc = llapi_layout_stripe_count_get(layout, &count);
1107 ASSERTF(rc == 0, "errno = %d\n", errno);
1108 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1110 rc = llapi_layout_stripe_size_get(layout, &size);
1111 ASSERTF(rc == 0, "errno = %d\n", errno);
1112 ASSERTF(size == T26_STRIPE_SIZE, "size = %"PRIu64, size);
1114 rc = llapi_layout_pattern_get(layout, &pattern);
1115 ASSERTF(rc == 0, "errno = %d\n", errno);
1116 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1118 llapi_layout_free(layout);
1121 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) work with
1122 * non existing file. */
1123 #define T27DIR "d27"
1124 #define T27_DESC "LAYOUT_GET_EXPECTED with non existing file"
1125 #define T27_STRIPE_SIZE (1048576 * 3)
1129 struct llapi_layout *layout;
1130 const char *lfs = getenv("LFS");
1134 char dirpath[PATH_MAX + 128];
1135 char filepath[PATH_MAX * 2];
1136 char cmd[PATH_MAX * 2];
1138 snprintf(dirpath, sizeof(dirpath) - 1, "%s/%s", lustre_dir, T27DIR);
1139 snprintf(filepath, sizeof(filepath), "%s/nonesuch", dirpath);
1141 rc = rmdir(dirpath);
1142 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1143 rc = mkdir(dirpath, 0750);
1144 ASSERTF(rc == 0, "errno = %d", errno);
1147 lfs = "/usr/bin/lfs";
1149 snprintf(cmd, sizeof(cmd), "%s setstripe -S %d %s", lfs,
1150 T27_STRIPE_SIZE, dirpath);
1152 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1154 layout = llapi_layout_get_by_path(filepath, LAYOUT_GET_EXPECTED);
1155 ASSERTF(layout != NULL, "errno = %d\n", errno);
1157 rc = llapi_layout_stripe_count_get(layout, &count);
1158 ASSERTF(rc == 0, "errno = %d\n", errno);
1159 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1161 rc = llapi_layout_stripe_size_get(layout, &size);
1162 ASSERTF(rc == 0, "errno = %d\n", errno);
1163 ASSERTF(size == T27_STRIPE_SIZE, "size = %"PRIu64, size);
1165 rc = llapi_layout_pattern_get(layout, &pattern);
1166 ASSERTF(rc == 0, "errno = %d\n", errno);
1167 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1169 llapi_layout_free(layout);
1172 /* llapi_layout_stripe_count_get returns LLAPI_LAYOUT_WIDE for a directory
1173 * with a stripe_count of -1. */
1174 #define T28DIR "d28"
1175 #define T28_DESC "LLAPI_LAYOUT_WIDE returned as expected"
1179 struct llapi_layout *layout;
1180 const char *lfs = getenv("LFS");
1182 char dirpath[PATH_MAX];
1183 char cmd[PATH_MAX + 64];
1185 snprintf(dirpath, sizeof(dirpath), "%s/%s", lustre_dir, T28DIR);
1187 rc = rmdir(dirpath);
1188 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1189 rc = mkdir(dirpath, 0750);
1190 ASSERTF(rc == 0, "errno = %d", errno);
1193 lfs = "/usr/bin/lfs";
1195 snprintf(cmd, sizeof(cmd), "%s setstripe -c -1 %s", lfs, dirpath);
1197 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1199 layout = llapi_layout_get_by_path(dirpath, 0);
1200 ASSERTF(layout != NULL, "errno = %d\n", errno);
1202 rc = llapi_layout_stripe_count_get(layout, &count);
1203 ASSERTF(rc == 0, "errno = %d\n", errno);
1204 ASSERTF(count == LLAPI_LAYOUT_WIDE, "count = %"PRIu64"\n", count);
1206 llapi_layout_free(layout);
1209 #define T29FILE "f29"
1210 #define T29_DESC "set ost index to non-zero stripe number"
1214 uint64_t ost0, ost1, nost;
1215 struct llapi_layout *layout;
1216 char path[PATH_MAX];
1221 layout = llapi_layout_alloc();
1222 ASSERTF(layout != NULL, "errno %d", errno);
1224 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T29FILE);
1227 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1229 /* set ost index to LLAPI_LAYOUT_IDX_MAX should fail */
1230 rc = llapi_layout_ost_index_set(layout, 1, LLAPI_LAYOUT_IDX_MAX);
1231 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d\n",
1234 /* specify ost index partially */
1235 rc = llapi_layout_ost_index_set(layout, 1, 0);
1236 ASSERTF(rc == 0, "errno = %d", errno);
1238 /* create a partially specified layout will fail */
1239 fd = llapi_layout_file_create(path, 0, 0660, layout);
1240 ASSERTF(fd == -1 && errno == EINVAL, "path = %s, fd = %d, errno = %d",
1244 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1246 /* specify all stripes */
1247 rc = llapi_layout_ost_index_set(layout, 0, 1);
1248 ASSERTF(rc == 0, "errno = %d", errno);
1251 fd = llapi_layout_file_create(path, 0, 0660, layout);
1252 ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1255 ASSERTF(rc == 0, "errno = %d", errno);
1256 llapi_layout_free(layout);
1258 /* get layout from file */
1259 layout = llapi_layout_get_by_path(path, 0);
1260 ASSERTF(layout != NULL, "errno = %d", errno);
1262 rc = llapi_layout_ost_index_get(layout, 0, &ost0);
1263 ASSERTF(rc == 0, "errno = %d", errno);
1264 rc = llapi_layout_ost_index_get(layout, 1, &ost1);
1265 ASSERTF(rc == 0, "errno = %d", errno);
1266 ASSERTF(ost0 == 1, "%"PRIu64" != %d", ost0, 1);
1267 ASSERTF(ost1 == 0, "%"PRIu64" != %d", ost1, 0);
1268 llapi_layout_free(layout);
1270 /* specify more ost indexes to test realloc */
1272 layout = llapi_layout_alloc();
1273 ASSERTF(layout != NULL, "errno %d", errno);
1274 for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++) {
1275 rc = llapi_layout_ost_index_set(layout, i, nost);
1276 ASSERTF(rc == 0, "errno = %d", errno);
1277 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1278 ASSERTF(rc == 0, "errno = %d", errno);
1280 if (nost == num_osts)
1285 for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++) {
1286 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1287 ASSERTF(rc == 0, "errno = %d", errno);
1288 ASSERTF(ost0 == nost, "ost=%"PRIu64" nost=%"PRIu64"",
1291 if (nost == num_osts)
1294 llapi_layout_free(layout);
1297 layout = llapi_layout_alloc();
1298 ASSERTF(layout != NULL, "errno %d", errno);
1299 for (i = LOV_MAX_STRIPE_COUNT-1; i >= 0; i--) {
1300 rc = llapi_layout_ost_index_set(layout, i, nost);
1301 ASSERTF(rc == 0, "errno = %d", errno);
1302 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1303 ASSERTF(rc == 0, "errno = %d", errno);
1305 if (nost == num_osts)
1310 for (i = LOV_MAX_STRIPE_COUNT-1; i <= 0; i--) {
1311 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1312 ASSERTF(rc == 0, "errno = %d", errno);
1313 ASSERTF(ost0 == nost, "ost=%"PRIu64", nost=%"PRIu64"",
1316 if (nost == num_osts)
1319 llapi_layout_free(layout);
1322 #define T30FILE "f30"
1323 #define T30_DESC "create composite file, traverse components"
1327 uint64_t start[3], end[3];
1329 struct llapi_layout *layout;
1330 char path[PATH_MAX];
1333 end[0] = 64 * 1024 * 1024; /* 64m */
1335 end[1] = 1 * 1024 * 1024 * 1024; /* 1G */
1337 end[2] = LUSTRE_EOF;
1342 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T30FILE);
1345 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1347 layout = llapi_layout_alloc();
1348 ASSERTF(layout != NULL, "errno %d", errno);
1350 rc = llapi_layout_stripe_count_set(layout, 1);
1351 ASSERTF(rc == 0, "errno %d", errno);
1353 /* add component without adjusting previous component's extent
1355 rc = llapi_layout_comp_add(layout);
1356 ASSERTF(rc == -1 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1358 rc = llapi_layout_comp_extent_set(layout, start[0], end[0]);
1359 ASSERTF(rc == 0, "errno %d", errno);
1361 rc = llapi_layout_comp_add(layout);
1362 ASSERTF(rc == 0, "errno %d", errno);
1364 /* set non-contiguous extent will fail */
1365 rc = llapi_layout_comp_extent_set(layout, start[1] * 2, end[1]);
1366 ASSERTF(rc == 0, "errno %d", errno);
1367 rc = llapi_layout_sanity(layout, false, false);
1368 ASSERTF(rc == 12 /*LSE_NOT_ADJACENT_PREV*/, "rc %d", rc);
1370 rc = llapi_layout_comp_extent_set(layout, start[1], end[1]);
1371 ASSERTF(rc == 0, "errno %d", errno);
1373 rc = llapi_layout_comp_add(layout);
1374 ASSERTF(rc == 0, "errno %d", errno);
1376 rc = llapi_layout_comp_extent_set(layout, start[2], end[2]);
1377 ASSERTF(rc == 0, "errno %d", errno);
1379 /* create composite file */
1380 fd = llapi_layout_file_create(path, 0, 0660, layout);
1381 ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1383 llapi_layout_free(layout);
1385 /* traverse & verify all components */
1386 layout = llapi_layout_get_by_path(path, 0);
1387 ASSERTF(layout != NULL, "errno = %d", errno);
1389 /* current component should be the tail component */
1390 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1391 ASSERTF(rc == 0, "errno %d", errno);
1392 ASSERTF(s == start[2] && e == end[2],
1393 "s: %"PRIu64", e: %"PRIu64"", s, e);
1395 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1396 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1398 /* delete non-tail component will fail */
1399 rc = llapi_layout_comp_del(layout);
1400 ASSERTF(rc == -1 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1402 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1403 ASSERTF(rc == 0, "errno %d", errno);
1404 ASSERTF(s == start[0] && e == end[0],
1405 "s: %"PRIu64", e: %"PRIu64"", s, e);
1407 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
1408 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1410 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1411 ASSERTF(rc == 0, "errno %d", errno);
1412 ASSERTF(s == start[1] && e == end[1],
1413 "s: %"PRIu64", e: %"PRIu64"", s, e);
1415 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
1416 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1418 rc = llapi_layout_comp_del(layout);
1419 ASSERTF(rc == 0, "errno %d", errno);
1421 llapi_layout_free(layout);
1424 #define T31FILE "f31"
1425 #define T31_DESC "add/delete component to/from existing file"
1429 uint64_t start[2], end[2];
1432 struct llapi_layout *layout;
1433 char path[PATH_MAX];
1436 end[0] = 64 * 1024 * 1024; /* 64m */
1438 end[1] = LUSTRE_EOF;
1443 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T31FILE);
1446 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1448 layout = llapi_layout_alloc();
1449 ASSERTF(layout != NULL, "errno %d", errno);
1451 rc = llapi_layout_stripe_count_set(layout, 1);
1452 ASSERTF(rc == 0, "errno %d", errno);
1454 rc = llapi_layout_comp_extent_set(layout, start[0], end[0]);
1455 ASSERTF(rc == 0, "errno %d", errno);
1457 /* create composite file */
1458 fd = llapi_layout_file_create(path, 0, 0660, layout);
1459 ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1460 llapi_layout_free(layout);
1462 layout = llapi_layout_alloc();
1463 ASSERTF(layout != NULL, "errno %d", errno);
1465 rc = llapi_layout_stripe_count_set(layout, 2);
1466 ASSERTF(rc == 0, "errno %d", errno);
1468 rc = llapi_layout_comp_extent_set(layout, start[1], end[1]);
1469 ASSERTF(rc == 0, "errno %d", errno);
1471 /* add comopnent to existing file */
1472 rc = llapi_layout_file_comp_add(path, layout);
1473 ASSERTF(rc == 0, "errno %d", errno);
1474 llapi_layout_free(layout);
1476 /* verify the composite layout after adding */
1477 layout = llapi_layout_get_by_path(path, 0);
1478 ASSERTF(layout != NULL, "errno = %d", errno);
1480 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1481 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1484 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1485 ASSERTF(rc == 0 && i < 2, "i %d, errno %d", i, errno);
1486 ASSERTF(s == start[i] && e == end[i],
1487 "i: %d s: %"PRIu64", e: %"PRIu64"", i, s, e);
1489 rc = llapi_layout_comp_id_get(layout, &id[i]);
1490 ASSERTF(rc == 0 && id[i] != 0, "i %d, errno %d, id %d",
1493 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
1494 ASSERTF(rc == 0 || i == 1, "i=%d rc=%d errno=%d", i, rc, errno);
1498 /* Verify reverse iteration gives the same IDs as forward iteration */
1499 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_LAST);
1500 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1505 rc = llapi_layout_comp_id_get(layout, &comp_id);
1506 ASSERTF(rc == 0 && comp_id == id[i],
1507 "i %d, errno %d, id[] %u/%u", i, errno, id[i], comp_id);
1509 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_PREV);
1510 ASSERTF(rc == 0 || i == 0, "i=%d rc=%d errno=%d", i, rc, errno);
1513 llapi_layout_free(layout);
1515 /* delete non-tail component will fail */
1516 rc = llapi_layout_file_comp_del(path, id[0], 0);
1517 ASSERTF(rc < 0 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1519 rc = llapi_layout_file_comp_del(path, id[1], 0);
1520 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1522 /* verify the composite layout after deleting */
1523 layout = llapi_layout_get_by_path(path, 0);
1524 ASSERTF(layout != NULL, "errno = %d", errno);
1526 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1527 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1529 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1530 ASSERTF(rc == 0, "errno %d", errno);
1531 ASSERTF(s == start[0] && e == end[0],
1532 "s: %"PRIu64", e: %"PRIu64"", s, e);
1535 #define T32FILE "t32"
1536 #define T32_STRIPE_COUNT (num_osts*2)
1537 #define T32_DESC "Test overstriping with layout_file_create"
1543 struct llapi_layout *layout = llapi_layout_alloc();
1544 void *lmdbuf = NULL;
1545 struct lov_user_md *lmd;
1546 char path[PATH_MAX];
1548 ASSERTF(layout != NULL, "errno %d", errno);
1550 /* Maximum possible, to be on the safe side - num_osts could be large */
1551 lmdbuf = malloc(XATTR_SIZE_MAX);
1552 ASSERTF(lmdbuf != NULL, "errno %d", errno);
1555 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T32FILE);
1558 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1561 rc = llapi_layout_stripe_count_set(layout, T32_STRIPE_COUNT);
1562 ASSERTF(rc == 0, "errno = %d", errno);
1563 rc = llapi_layout_stripe_count_get(layout, &count);
1564 ASSERTF(rc == 0 && count == T32_STRIPE_COUNT, "%"PRIu64" != %d", count,
1567 rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_OVERSTRIPING);
1568 ASSERTF(rc == 0, "errno = %d", errno);
1571 fd = llapi_layout_file_create(path, 0, 0660, layout);
1572 ASSERTF(fd >= 0, "path = %s, errno = %d", path, errno);
1574 rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE_NEW, lmdbuf);
1575 ASSERTF(rc == 0, "errno = %d", errno);
1577 count = lmd->lmm_stripe_count;
1578 ASSERTF(count == T32_STRIPE_COUNT,
1579 "stripe count (%"PRIu64") not equal to expected (%d)",
1580 count, T32_STRIPE_COUNT);
1583 ASSERTF(rc == 0, "errno = %d", errno);
1584 llapi_layout_free(layout);
1588 #define T33FILE "t33"
1589 #define T33_STRIPE_COUNT (num_osts*2)
1590 #define T33_DESC "Test overstriping with llapi_file_open"
1596 void *lmdbuf = NULL;
1597 struct lov_user_md *lmd;
1598 char path[PATH_MAX];
1600 /* Maximum possible, to be on the safe side - num_osts could be large */
1601 lmdbuf = malloc(XATTR_SIZE_MAX);
1602 ASSERTF(lmdbuf != NULL, "errno %d", errno);
1605 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T33FILE);
1608 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1610 fd = llapi_file_open(path, O_CREAT | O_RDWR, 0660, 0, -1, num_osts*2,
1611 LOV_PATTERN_RAID0 | LOV_PATTERN_OVERSTRIPING);
1612 ASSERTF(fd >= 0, "path = %s, errno = %d", path, errno);
1614 rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE_NEW, lmdbuf);
1615 ASSERTF(rc == 0, "errno = %d", errno);
1617 count = lmd->lmm_stripe_count;
1618 ASSERTF(count == T33_STRIPE_COUNT,
1619 "stripe count (%"PRIu64") not equal to expected (%d)",
1620 count, T33_STRIPE_COUNT);
1623 ASSERTF(rc == 0, "errno = %d", errno);
1627 #define T34FILE "f34"
1628 #define T34_DESC "create simple valid & invalid self extending layouts"
1632 uint64_t start[4], end[4];
1633 struct llapi_layout *layout;
1634 char path[PATH_MAX];
1637 end[0] = 10 * 1024 * 1024; /* 10m */
1639 end[1] = 1024 * 1024 * 1024; /* 1G */
1641 end[2] = 10ull * 1024 * 1024 * 1024; /* 10G */
1643 end[3] = LUSTRE_EOF;
1648 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T34FILE);
1651 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1653 layout = llapi_layout_alloc();
1654 ASSERTF(layout != NULL, "errno %d", errno);
1656 rc = llapi_layout_stripe_count_set(layout, 1);
1657 ASSERTF(rc == 0, "errno %d", errno);
1659 /* add component without adjusting previous component's extent
1662 rc = llapi_layout_comp_add(layout);
1663 ASSERTF(rc == -1 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1665 rc = llapi_layout_comp_extent_set(layout, start[0], end[0]);
1666 ASSERTF(rc == 0, "errno %d", errno);
1668 rc = llapi_layout_comp_add(layout);
1669 ASSERTF(rc == 0, "errno %d", errno);
1671 rc = llapi_layout_comp_extent_set(layout, start[1], end[1]);
1672 ASSERTF(rc == 0, "errno %d", errno);
1674 rc = llapi_layout_comp_flags_set(layout, LCME_FL_EXTENSION);
1675 ASSERTF(rc == 0, "errno %d", errno);
1677 /* Invalid size, too small - < 64 MiB */
1678 rc = llapi_layout_extension_size_set(layout, 32 << 20);
1679 ASSERTF(rc == -1, "errno %d", errno);
1681 /* too large - > 4 TiB */
1682 rc = llapi_layout_extension_size_set(layout, 5ull << 40);
1683 ASSERTF(rc == -1, "errno %d", errno);
1685 /* Valid size, 64 MiB */
1686 rc = llapi_layout_extension_size_set(layout, 64 << 20);
1687 ASSERTF(rc == 0, "errno %d", errno);
1689 rc = llapi_layout_comp_add(layout);
1690 ASSERTF(rc == 0, "errno %d", errno);
1692 rc = llapi_layout_comp_extent_set(layout, start[2], end[2]);
1693 ASSERTF(rc == 0, "errno %d", errno);
1695 /* Set extension space flag on adjacent components:
1696 * This is invalid, but can't be checked until we try to create the
1698 rc = llapi_layout_comp_flags_set(layout, LCME_FL_EXTENSION);
1699 ASSERTF(rc == 0, "errno %d", errno);
1701 fd = llapi_layout_file_create(path, 0, 0660, layout);
1702 ASSERTF(fd = -1, "path = %s, fd = %d, errno = %d", path, fd, errno);
1704 /* Delete incorrect component */
1705 rc = llapi_layout_comp_del(layout);
1706 ASSERTF(rc == 0, "errno %d", errno);
1708 rc = llapi_layout_comp_add(layout);
1709 ASSERTF(rc == 0, "errno %d", errno);
1711 /* Convert this comp to zero-length so it can be followed by extension
1713 rc = llapi_layout_comp_extent_set(layout, start[2], start[2]);
1714 ASSERTF(rc == 0, "errno %d", errno);
1716 rc = llapi_layout_comp_add(layout);
1717 ASSERTF(rc == 0, "errno %d", errno);
1719 rc = llapi_layout_comp_extent_set(layout, start[2], end[3]);
1720 ASSERTF(rc == 0, "errno %d", errno);
1722 rc = llapi_layout_comp_flags_set(layout, LCME_FL_EXTENSION);
1723 ASSERTF(rc == 0, "errno %d", errno);
1725 /* create composite file */
1726 fd = llapi_layout_file_create(path, 0, 0660, layout);
1727 ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1729 llapi_layout_free(layout);
1731 /* traverse & verify all components */
1732 layout = llapi_layout_get_by_path(path, 0);
1733 ASSERTF(layout != NULL, "errno = %d", errno);
1735 rc = llapi_layout_sanity(layout, false, false);
1736 ASSERTF(rc == 0, "errno %d", errno);
1739 #define TEST_DESC_LEN 80
1740 struct test_tbl_entry {
1741 void (*tte_fn)(void);
1742 char tte_desc[TEST_DESC_LEN];
1746 static struct test_tbl_entry test_tbl[] = {
1747 { .tte_fn = &test0, .tte_desc = T0_DESC, .tte_skip = false },
1748 { .tte_fn = &test1, .tte_desc = T1_DESC, .tte_skip = false },
1749 { .tte_fn = &test2, .tte_desc = T2_DESC, .tte_skip = false },
1750 { .tte_fn = &test3, .tte_desc = T3_DESC, .tte_skip = false },
1751 { .tte_fn = &test4, .tte_desc = T4_DESC, .tte_skip = false },
1752 { .tte_fn = &test5, .tte_desc = T5_DESC, .tte_skip = false },
1753 { .tte_fn = &test6, .tte_desc = T6_DESC, .tte_skip = false },
1754 { .tte_fn = &test7, .tte_desc = T7_DESC, .tte_skip = false },
1755 { .tte_fn = &test8, .tte_desc = T8_DESC, .tte_skip = false },
1756 { .tte_fn = &test9, .tte_desc = T9_DESC, .tte_skip = false },
1757 { .tte_fn = &test10, .tte_desc = T10_DESC, .tte_skip = false },
1758 { .tte_fn = &test11, .tte_desc = T11_DESC, .tte_skip = false },
1759 { .tte_fn = &test12, .tte_desc = T12_DESC, .tte_skip = false },
1760 { .tte_fn = &test13, .tte_desc = T13_DESC, .tte_skip = false },
1761 { .tte_fn = &test14, .tte_desc = T14_DESC, .tte_skip = false },
1762 { .tte_fn = &test15, .tte_desc = T15_DESC, .tte_skip = false },
1763 { .tte_fn = &test16, .tte_desc = T16_DESC, .tte_skip = false },
1764 { .tte_fn = &test17, .tte_desc = T17_DESC, .tte_skip = false },
1765 { .tte_fn = &test18, .tte_desc = T18_DESC, .tte_skip = false },
1766 { .tte_fn = &test19, .tte_desc = T19_DESC, .tte_skip = false },
1767 { .tte_fn = &test20, .tte_desc = T20_DESC, .tte_skip = false },
1768 { .tte_fn = &test21, .tte_desc = T21_DESC, .tte_skip = false },
1769 { .tte_fn = &test22, .tte_desc = T22_DESC, .tte_skip = false },
1770 { .tte_fn = &test23, .tte_desc = T23_DESC, .tte_skip = false },
1771 { .tte_fn = &test24, .tte_desc = T24_DESC, .tte_skip = false },
1772 { .tte_fn = &test25, .tte_desc = T25_DESC, .tte_skip = false },
1773 { .tte_fn = &test26, .tte_desc = T26_DESC, .tte_skip = false },
1774 { .tte_fn = &test27, .tte_desc = T27_DESC, .tte_skip = false },
1775 { .tte_fn = &test28, .tte_desc = T28_DESC, .tte_skip = false },
1776 { .tte_fn = &test29, .tte_desc = T29_DESC, .tte_skip = false },
1777 { .tte_fn = &test30, .tte_desc = T30_DESC, .tte_skip = false },
1778 { .tte_fn = &test31, .tte_desc = T31_DESC, .tte_skip = false },
1779 { .tte_fn = &test32, .tte_desc = T32_DESC, .tte_skip = false },
1780 { .tte_fn = &test33, .tte_desc = T33_DESC, .tte_skip = false },
1781 { .tte_fn = &test34, .tte_desc = T34_DESC, .tte_skip = false },
1784 #define NUM_TESTS (sizeof(test_tbl) / sizeof(struct test_tbl_entry))
1786 void print_test_desc(int test_num, const char *test_desc, const char *status)
1790 printf(" test %2d: %s ", test_num, test_desc);
1791 for (i = 0; i < TEST_DESC_LEN - strlen(test_desc); i++)
1793 printf(" %s\n", status);
1796 /* This function runs a single test by forking the process. This way,
1797 * if there is a segfault during a test, the test program won't crash. */
1798 int test(void (*test_fn)(), const char *test_desc, bool test_skip, int test_num)
1802 char status_buf[128];
1805 print_test_desc(test_num, test_desc, "skip");
1811 ERROR("cannot fork: %s", strerror(errno));
1812 } else if (pid > 0) {
1815 /* Non-zero value indicates failure. */
1818 strncpy(status_buf, "pass", sizeof(status_buf));
1819 } else if WIFSIGNALED(status) {
1820 snprintf(status_buf, sizeof(status_buf),
1821 "fail (exit status %d, killed by SIG%d)",
1822 WEXITSTATUS(status), WTERMSIG(status));
1825 snprintf(status_buf, sizeof(status_buf),
1826 "fail (exit status %d)", WEXITSTATUS(status));
1829 print_test_desc(test_num, test_desc, status_buf);
1830 } else if (pid == 0) {
1831 /* Run the test in the child process. Exit with 0 for success,
1832 * non-zero for failure */
1840 /* 'str_tests' are the tests to be skipped, such as "1,3,4,.." */
1841 static void set_tests_skipped(char *str_tests)
1843 char *ptr = str_tests;
1846 if (ptr == NULL || strlen(ptr) == 0)
1849 while (*ptr != '\0') {
1850 tstno = strtoul(ptr, &ptr, 0);
1851 if (tstno >= 0 && tstno < NUM_TESTS)
1852 test_tbl[tstno].tte_skip = true;
1860 static void process_args(int argc, char *argv[])
1864 while ((c = getopt(argc, argv, "d:p:o:s:")) != -1) {
1867 lustre_dir = optarg;
1873 num_osts = atoi(optarg);
1876 set_tests_skipped(optarg);
1879 fprintf(stderr, "Unknown option '%c'\n", optopt);
1885 int main(int argc, char *argv[])
1892 llapi_msg_set_level(LLAPI_MSG_OFF);
1894 process_args(argc, argv);
1895 if (lustre_dir == NULL)
1896 lustre_dir = "/mnt/lustre";
1897 if (poolname == NULL)
1898 poolname = "testpool";
1903 DIE("Error: at least 2 OSTS are required\n");
1905 if (stat(lustre_dir, &s) < 0)
1906 DIE("cannot stat %s: %s\n", lustre_dir, strerror(errno));
1907 else if (!S_ISDIR(s.st_mode))
1908 DIE("%s: not a directory\n", lustre_dir);
1910 rc = llapi_search_fsname(lustre_dir, fsname);
1912 fprintf(stderr, "Error: %s: not a Lustre filesystem\n",
1917 /* Play nice with Lustre test scripts. Non-line buffered output
1918 * stream under I/O redirection may appear incorrectly. */
1919 setvbuf(stdout, NULL, _IOLBF, 0);
1921 for (i = 0; i < NUM_TESTS; i++) {
1922 struct test_tbl_entry *tst = &test_tbl[i];
1923 if (test(tst->tte_fn, tst->tte_desc, tst->tte_skip, i) != 0)