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 * 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,
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
40 #include <sys/signal.h>
41 #include <sys/types.h>
43 #include <lustre/lustreapi.h>
50 #define ERROR(fmt, ...) \
51 fprintf(stderr, "%s: %s:%d: %s: " fmt "\n", \
52 program_invocation_short_name, __FILE__, __LINE__, \
53 __func__, ## __VA_ARGS__);
55 #define DIE(fmt, ...) \
57 ERROR(fmt, ## __VA_ARGS__); \
61 #define ASSERTF(cond, fmt, ...) \
64 DIE("assertion '%s' failed: "fmt, #cond, ## __VA_ARGS__);\
67 static char *lustre_dir;
68 static char *poolname;
69 static int num_osts = -1;
71 void usage(char *prog)
73 printf("Usage: %s [-d lustre_dir] [-p pool_name] [-o num_osts] "
74 "[-s $n,$m,..]\n", prog);
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"
89 struct llapi_layout *layout = llapi_layout_alloc();
91 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
93 ASSERTF(layout != NULL, "errno %d", errno);
95 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
98 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
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,
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,
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);
123 rc = llapi_layout_ost_index_set(layout, 0, T0_OST_OFFSET);
124 ASSERTF(rc == 0, "errno = %d", errno);
127 fd = llapi_layout_file_create(path, 0, 0660, layout);
128 ASSERTF(fd >= 0, "path = %s, errno = %d", path, errno);
130 ASSERTF(rc == 0, "errno = %d", errno);
131 llapi_layout_free(layout);
134 void __test1_helper(struct llapi_layout *layout)
141 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
143 rc = llapi_layout_stripe_count_get(layout, &count);
144 ASSERTF(count == T0_STRIPE_COUNT, "%"PRIu64" != %d", count,
147 rc = llapi_layout_stripe_size_get(layout, &size);
148 ASSERTF(size == T0_STRIPE_SIZE, "%"PRIu64" != %d", size,
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);
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);
164 #define T1_DESC "Read test0 file by path and verify attributes"
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);
176 #define T2_DESC "Read test0 file by FD and verify attributes"
183 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
185 fd = open(path, O_RDONLY);
186 ASSERTF(fd >= 0, "open(%s): errno = %d", path, errno);
188 struct llapi_layout *layout = llapi_layout_get_by_fd(fd, 0);
189 ASSERTF(layout != NULL, "errno = %d", errno);
192 ASSERTF(rc == 0, "close(%s): errno = %d", path, errno);
194 __test1_helper(layout);
195 llapi_layout_free(layout);
198 #define T3_DESC "Read test0 file by FID and verify attributes"
202 struct llapi_layout *layout;
207 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
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);
214 layout = llapi_layout_get_by_fid(path, &fid, 0);
215 ASSERTF(layout != NULL, "fidstr = %s, errno = %d", fidstr, errno);
217 __test1_helper(layout);
218 llapi_layout_free(layout);
222 #define T4_STRIPE_COUNT 2
223 #define T4_STRIPE_SIZE 2097152
224 #define T4_DESC "Verify compatibility with 'lfs setstripe'"
232 const char *lfs = getenv("LFS");
233 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
237 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T4FILE);
240 lfs = "/usr/bin/lfs";
243 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
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);
249 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
252 struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
253 ASSERTF(layout != NULL, "errno = %d", errno);
255 rc = llapi_layout_stripe_count_get(layout, &count);
256 ASSERTF(count == T4_STRIPE_COUNT, "%"PRIu64" != %d", count,
259 rc = llapi_layout_stripe_size_get(layout, &size);
260 ASSERTF(size == T4_STRIPE_SIZE, "%"PRIu64" != %d", size,
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);
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);
274 llapi_layout_free(layout);
278 #define T5_DESC "llapi_layout_get_by_path ENOENT handling"
283 struct llapi_layout *layout;
285 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T5FILE);
288 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
291 layout = llapi_layout_get_by_path(path, 0);
292 ASSERTF(layout == NULL && errno == ENOENT, "errno = %d", errno);
295 #define T6_DESC "llapi_layout_get_by_fd EBADF handling"
299 struct llapi_layout *layout = llapi_layout_get_by_fd(9999, 0);
300 ASSERTF(layout == NULL && errno == EBADF, "errno = %d", errno);
304 #define T7_DESC "llapi_layout_get_by_path EACCES handling"
309 uid_t myuid = getuid();
311 const char *runas = getenv("RUNAS_ID");
315 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T7FILE);
316 ASSERTF(myuid == 0, "myuid = %d", myuid); /* Need root for this test. */
318 /* Create file as root */
320 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
322 fd = open(path, O_CREAT, 0400);
323 ASSERTF(fd > 0, "errno = %d", errno);
325 ASSERTF(rc == 0, "errno = %d", errno);
327 /* Become unprivileged user */
330 ASSERTF(uid != 0, "runas = %s", runas);
332 pw = getpwnam("nobody");
333 ASSERTF(pw != NULL, "errno = %d", errno);
337 ASSERTF(rc == 0, "errno = %d", errno);
339 struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
340 ASSERTF(layout == NULL && errno == EACCES, "errno = %d", errno);
342 ASSERTF(rc == 0, "errno = %d", errno);
345 /* llapi_layout_get_by_path() returns default layout for file with no
346 * striping attributes. */
348 #define T8_DESC "llapi_layout_get_by_path ENODATA handling"
353 struct llapi_layout *layout;
359 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T8FILE);
362 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
363 fd = open(path, O_CREAT, 0640);
364 ASSERTF(fd >= 0, "errno = %d", errno);
366 ASSERTF(rc == 0, "errno = %d", errno);
368 layout = llapi_layout_get_by_path(path, 0);
369 ASSERTF(layout != NULL, "errno = %d\n", errno);
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);
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);
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",
384 llapi_layout_free(layout);
387 /* Verify llapi_layout_patter_set() return values for various inputs. */
388 #define T9_DESC "verify llapi_layout_pattern_set() return values"
391 struct llapi_layout *layout;
394 layout = llapi_layout_alloc();
395 ASSERTF(layout != NULL, "errno = %d\n", errno);
398 rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_INVALID);
399 ASSERTF(rc == -1 && errno == EOPNOTSUPP, "rc = %d, errno = %d", rc,
403 rc = llapi_layout_pattern_set(NULL, LLAPI_LAYOUT_DEFAULT);
404 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc,
408 rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_DEFAULT);
409 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
412 rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_RAID0);
413 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
415 llapi_layout_free(layout);
418 /* Verify stripe_count interfaces return errors as expected */
419 #define T10_DESC "stripe_count error handling"
424 struct llapi_layout *layout;
426 layout = llapi_layout_alloc();
427 ASSERTF(layout != NULL, "errno = %d", errno);
429 /* invalid stripe count */
431 rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_INVALID);
432 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
435 rc = llapi_layout_stripe_count_set(layout, -1);
436 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
440 rc = llapi_layout_stripe_count_set(NULL, 2);
441 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
445 rc = llapi_layout_stripe_count_get(NULL, &count);
446 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
450 rc = llapi_layout_stripe_count_get(layout, NULL);
451 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
453 /* stripe count too large */
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);
460 /* Verify stripe_size interfaces return errors as expected */
461 #define T11_DESC "stripe_size error handling"
466 struct llapi_layout *layout;
468 layout = llapi_layout_alloc();
469 ASSERTF(layout != NULL, "errno = %d", errno);
471 /* negative stripe size */
473 rc = llapi_layout_stripe_size_set(layout, -1);
474 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
476 /* invalid stripe size */
478 rc = llapi_layout_stripe_size_set(layout, LLAPI_LAYOUT_INVALID);
479 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
481 /* stripe size too big */
483 rc = llapi_layout_stripe_size_set(layout, (1ULL << 33));
484 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
488 rc = llapi_layout_stripe_size_set(NULL, 1048576);
489 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
492 rc = llapi_layout_stripe_size_get(NULL, &size);
493 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
497 rc = llapi_layout_stripe_size_get(layout, NULL);
498 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
500 llapi_layout_free(layout);
503 /* Verify pool_name interfaces return errors as expected */
504 #define T12_DESC "pool_name error handling"
508 struct llapi_layout *layout;
509 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
511 layout = llapi_layout_alloc();
512 ASSERTF(layout != NULL, "errno = %d", errno);
516 rc = llapi_layout_pool_name_set(NULL, "foo");
517 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
521 rc = llapi_layout_pool_name_set(layout, NULL);
522 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
526 rc = llapi_layout_pool_name_get(NULL, mypool, sizeof(mypool));
527 ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
531 rc = llapi_layout_pool_name_get(layout, NULL, sizeof(mypool));
532 ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
534 /* Pool name too long*/
536 rc = llapi_layout_pool_name_set(layout, "0123456789abcdef");
537 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
539 llapi_layout_free(layout);
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"
551 struct llapi_layout *layout;
554 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T13FILE);
556 layout = llapi_layout_alloc();
557 ASSERTF(layout != NULL, "errno = %d", errno);
559 /* invalid OST index */
561 rc = llapi_layout_ost_index_set(layout, 0, LLAPI_LAYOUT_INVALID);
562 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
565 rc = llapi_layout_ost_index_set(layout, 0, -1);
566 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
570 rc = llapi_layout_ost_index_set(NULL, 0, 1);
571 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
574 rc = llapi_layout_ost_index_get(NULL, 0, &idx);
575 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
579 rc = llapi_layout_ost_index_get(layout, 0, NULL);
580 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
582 /* Layout not read from file so has no OST data. */
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);
589 /* n greater than stripe count*/
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);
597 ASSERTF(rc == 0, "errno = %d", errno);
598 llapi_layout_free(layout);
600 layout = llapi_layout_get_by_path(path, 0);
601 ASSERTF(layout != NULL, "errno = %d", errno);
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);
606 llapi_layout_free(layout);
609 /* Verify llapi_layout_file_create() returns errors as expected */
610 #define T14_DESC "llapi_layout_file_create error handling"
614 struct llapi_layout *layout = llapi_layout_alloc();
618 rc = llapi_layout_file_create(NULL, 0, 0, layout);
619 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
621 llapi_layout_free(layout);
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"
633 struct llapi_layout *layout;
636 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T15FILE);
639 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
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);
647 fd = llapi_layout_file_create(path, 0, 0640, layout);
648 ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
650 ASSERTF(rc == 0, "errno = %d", errno);
652 rc = llapi_layout_stripe_count_set(layout, T15_STRIPE_COUNT - 1);
654 fd = llapi_layout_file_open(path, 0, 0640, layout);
655 ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
657 ASSERTF(rc == 0, "errno = %d", errno);
658 llapi_layout_free(layout);
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);
668 /* Default stripe attributes are applied as expected. */
669 #define T16FILE "t16"
670 #define T16_DESC "Default stripe attributes are applied as expected"
675 struct llapi_layout *deflayout;
676 struct llapi_layout *filelayout;
683 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T16FILE);
686 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
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);
695 /* First, with a default struct llapi_layout */
696 filelayout = llapi_layout_alloc();
697 ASSERTF(filelayout != NULL, "errno = %d", errno);
699 fd = llapi_layout_file_create(path, 0, 0640, filelayout);
700 ASSERTF(fd >= 0, "errno = %d", errno);
703 ASSERTF(rc == 0, "errno = %d", errno);
705 llapi_layout_free(filelayout);
707 filelayout = llapi_layout_get_by_path(path, 0);
708 ASSERTF(filelayout != NULL, "errno = %d", errno);
710 rc = llapi_layout_stripe_count_get(filelayout, &fcount);
711 ASSERTF(rc == 0, "errno = %d", errno);
712 ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
713 dcount == LLAPI_LAYOUT_WIDE,
714 "%"PRIu64" != %"PRIu64, fcount, dcount);
716 rc = llapi_layout_stripe_size_get(filelayout, &fsize);
717 ASSERTF(rc == 0, "errno = %d", errno);
718 ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
720 /* NULL layout also implies default layout */
722 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
724 fd = llapi_layout_file_create(path, 0, 0640, filelayout);
725 ASSERTF(fd >= 0, "errno = %d", errno);
727 ASSERTF(rc == 0, "errno = %d", errno);
728 filelayout = llapi_layout_get_by_path(path, 0);
729 ASSERTF(filelayout != NULL, "errno = %d", errno);
731 rc = llapi_layout_stripe_count_get(filelayout, &fcount);
732 ASSERTF(rc == 0, "errno = %d", errno);
733 rc = llapi_layout_stripe_size_get(filelayout, &fsize);
734 ASSERTF(rc == 0, "errno = %d", errno);
735 ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
736 dcount == LLAPI_LAYOUT_WIDE,
737 "%"PRIu64" != %"PRIu64, fcount, dcount);
738 ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
740 llapi_layout_free(filelayout);
741 llapi_layout_free(deflayout);
744 /* Setting stripe count to LLAPI_LAYOUT_WIDE uses all available OSTs. */
745 #define T17FILE "t17"
746 #define T17_DESC "LLAPI_LAYOUT_WIDE is honored"
752 uint64_t osts_layout;
753 struct llapi_layout *layout;
756 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T17FILE);
759 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
760 layout = llapi_layout_alloc();
761 ASSERTF(layout != NULL, "errno = %d", errno);
762 rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_WIDE);
763 ASSERTF(rc == 0, "errno = %d", errno);
764 fd = llapi_layout_file_create(path, 0, 0640, layout);
765 ASSERTF(fd >= 0, "errno = %d", errno);
767 ASSERTF(rc == 0, "errno = %d", errno);
768 llapi_layout_free(layout);
770 /* Get number of available OSTs */
771 fd = open(path, O_RDONLY);
772 ASSERTF(fd >= 0, "errno = %d", errno);
773 rc = llapi_lov_get_uuids(fd, NULL, &osts_all);
774 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
776 ASSERTF(rc == 0, "errno = %d", errno);
778 layout = llapi_layout_get_by_path(path, 0);
779 ASSERTF(layout != NULL, "errno = %d", errno);
780 rc = llapi_layout_stripe_count_get(layout, &osts_layout);
781 ASSERTF(osts_layout == osts_all, "%"PRIu64" != %d", osts_layout,
784 llapi_layout_free(layout);
787 /* Setting pool with "fsname.pool" notation. */
788 #define T18FILE "t18"
789 #define T18_DESC "Setting pool with fsname.pool notation"
794 struct llapi_layout *layout = llapi_layout_alloc();
796 char pool[LOV_MAXPOOLNAME*2 + 1];
797 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
799 snprintf(pool, sizeof(pool), "lustre.%s", poolname);
801 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T18FILE);
803 ASSERTF(layout != NULL, "errno = %d", errno);
806 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
808 rc = llapi_layout_pool_name_set(layout, pool);
809 ASSERTF(rc == 0, "errno = %d", errno);
811 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
812 ASSERTF(rc == 0, "errno = %d", errno);
813 rc = strcmp(mypool, poolname);
814 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
815 fd = llapi_layout_file_create(path, 0, 0640, layout);
816 ASSERTF(fd >= 0, "errno = %d", errno);
818 ASSERTF(rc == 0, "errno = %d", errno);
820 llapi_layout_free(layout);
822 layout = llapi_layout_get_by_path(path, 0);
823 ASSERTF(layout != NULL, "errno = %d", errno);
824 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
825 ASSERTF(rc == 0, "errno = %d", errno);
826 rc = strcmp(mypool, poolname);
827 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
828 llapi_layout_free(layout);
831 #define T19_DESC "Maximum length pool name is NULL-terminated"
834 struct llapi_layout *layout;
835 char *name = "0123456789abcde";
836 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
839 layout = llapi_layout_alloc();
840 ASSERTF(layout != NULL, "errno = %d", errno);
841 rc = llapi_layout_pool_name_set(layout, name);
842 ASSERTF(rc == 0, "errno = %d", errno);
843 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
844 ASSERTF(strlen(name) == strlen(mypool), "name = %s, str = %s", name,
846 llapi_layout_free(layout);
849 #define T20FILE "t20"
850 #define T20_DESC "LLAPI_LAYOUT_DEFAULT is honored"
855 struct llapi_layout *deflayout;
856 struct llapi_layout *filelayout;
863 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T20FILE);
866 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
868 filelayout = llapi_layout_alloc();
869 ASSERTF(filelayout != NULL, "errno = %d", errno);
871 rc = llapi_layout_stripe_size_set(filelayout, LLAPI_LAYOUT_DEFAULT);
872 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
874 rc = llapi_layout_stripe_count_set(filelayout, LLAPI_LAYOUT_DEFAULT);
875 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
877 fd = llapi_layout_file_create(path, 0, 0640, filelayout);
878 ASSERTF(fd >= 0, "errno = %d", errno);
881 ASSERTF(rc == 0, "errno = %d", errno);
883 llapi_layout_free(filelayout);
885 deflayout = llapi_layout_get_by_path(lustre_dir, LAYOUT_GET_EXPECTED);
886 ASSERTF(deflayout != NULL, "errno = %d", errno);
888 filelayout = llapi_layout_get_by_path(path, 0);
889 ASSERTF(filelayout != NULL, "errno = %d", errno);
891 rc = llapi_layout_stripe_count_get(filelayout, &fcount);
892 ASSERTF(rc == 0, "errno = %d", errno);
893 rc = llapi_layout_stripe_count_get(deflayout, &dcount);
894 ASSERTF(rc == 0, "errno = %d", errno);
895 ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
896 dcount == LLAPI_LAYOUT_WIDE,
897 "%"PRIu64" != %"PRIu64, fcount, dcount);
899 rc = llapi_layout_stripe_size_get(filelayout, &fsize);
900 ASSERTF(rc == 0, "errno = %d", errno);
901 rc = llapi_layout_stripe_size_get(deflayout, &dsize);
902 ASSERTF(rc == 0, "errno = %d", errno);
903 ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
905 llapi_layout_free(filelayout);
906 llapi_layout_free(deflayout);
909 #define T21_DESC "llapi_layout_file_create fails for non-Lustre file"
912 struct llapi_layout *layout;
913 char template[PATH_MAX];
917 snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
918 fd = mkstemp(template);
919 ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
921 ASSERTF(rc == 0, "errno = %d", fd);
922 rc = unlink(template);
923 ASSERTF(rc == 0, "errno = %d", errno);
925 layout = llapi_layout_alloc();
926 ASSERTF(layout != NULL, "errno = %d", errno);
928 fd = llapi_layout_file_create(template, 0, 0640, layout);
929 ASSERTF(fd == -1 && errno == ENOTTY,
930 "fd = %d, errno = %d, template = %s", fd, errno, template);
931 llapi_layout_free(layout);
934 #define T22FILE "t22"
935 #define T22_DESC "llapi_layout_file_create applied mode correctly"
942 mode_t mode_in = 0640;
946 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T22FILE);
949 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
951 umask_orig = umask(S_IWGRP | S_IWOTH);
953 fd = llapi_layout_file_create(path, 0, mode_in, NULL);
954 ASSERTF(fd >= 0, "errno = %d", errno);
956 (void) umask(umask_orig);
959 ASSERTF(rc == 0, "errno = %d", errno);
962 ASSERTF(rc == 0, "errno = %d", fd);
964 mode_out = st.st_mode & ~S_IFMT;
965 ASSERTF(mode_in == mode_out, "%o != %o", mode_in, mode_out);
968 #define T23_DESC "llapi_layout_get_by_path fails for non-Lustre file"
971 struct llapi_layout *layout;
972 char template[PATH_MAX];
976 snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
977 fd = mkstemp(template);
978 ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
980 ASSERTF(rc == 0, "errno = %d", fd);
982 layout = llapi_layout_get_by_path(template, 0);
983 ASSERTF(layout == NULL && errno == ENOTTY,
984 "errno = %d, template = %s", errno, template);
986 rc = unlink(template);
987 ASSERTF(rc == 0, "errno = %d", errno);
990 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
991 * for file with unspecified layout. */
992 #define T24FILE "t24"
993 #define T24_DESC "LAYOUT_GET_EXPECTED works with existing file"
998 struct llapi_layout *layout;
1002 char path[PATH_MAX];
1004 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T24FILE);
1007 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1008 fd = open(path, O_CREAT, 0640);
1009 ASSERTF(fd >= 0, "errno = %d", errno);
1011 ASSERTF(rc == 0, "errno = %d", errno);
1013 layout = llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED);
1014 ASSERTF(layout != NULL, "errno = %d\n", errno);
1016 rc = llapi_layout_stripe_count_get(layout, &count);
1017 ASSERTF(rc == 0, "errno = %d\n", errno);
1018 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1020 rc = llapi_layout_stripe_size_get(layout, &size);
1021 ASSERTF(rc == 0, "errno = %d\n", errno);
1022 ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1024 rc = llapi_layout_pattern_get(layout, &pattern);
1025 ASSERTF(rc == 0, "errno = %d\n", errno);
1026 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1028 llapi_layout_free(layout);
1031 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
1032 * for directory with unspecified layout. */
1033 #define T25DIR "d25"
1034 #define T25_DESC "LAYOUT_GET_EXPECTED works with directory"
1038 struct llapi_layout *layout;
1044 snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T25DIR);
1047 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1048 rc = mkdir(dir, 0750);
1049 ASSERTF(rc == 0, "errno = %d", errno);
1051 layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1052 ASSERTF(layout != NULL, "errno = %d\n", errno);
1054 rc = llapi_layout_stripe_count_get(layout, &count);
1055 ASSERTF(rc == 0, "errno = %d\n", errno);
1056 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1058 rc = llapi_layout_stripe_size_get(layout, &size);
1059 ASSERTF(rc == 0, "errno = %d\n", errno);
1060 ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1062 rc = llapi_layout_pattern_get(layout, &pattern);
1063 ASSERTF(rc == 0, "errno = %d\n", errno);
1064 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1066 llapi_layout_free(layout);
1069 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) correctly combines
1070 * specified attributes of parent directory with attributes filesystem root. */
1071 #define T26DIR "d26"
1072 #define T26_DESC "LAYOUT_GET_EXPECTED partially specified parent"
1073 #define T26_STRIPE_SIZE (1048576 * 4)
1077 struct llapi_layout *layout;
1078 const char *lfs = getenv("LFS");
1085 snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T26DIR);
1087 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1088 rc = mkdir(dir, 0750);
1089 ASSERTF(rc == 0, "errno = %d", errno);
1092 lfs = "/usr/bin/lfs";
1094 snprintf(cmd, sizeof(cmd), "%s setstripe -S %d %s", lfs,
1095 T26_STRIPE_SIZE, dir);
1097 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1099 layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1100 ASSERTF(layout != NULL, "errno = %d\n", errno);
1102 rc = llapi_layout_stripe_count_get(layout, &count);
1103 ASSERTF(rc == 0, "errno = %d\n", errno);
1104 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1106 rc = llapi_layout_stripe_size_get(layout, &size);
1107 ASSERTF(rc == 0, "errno = %d\n", errno);
1108 ASSERTF(size == T26_STRIPE_SIZE, "size = %"PRIu64, size);
1110 rc = llapi_layout_pattern_get(layout, &pattern);
1111 ASSERTF(rc == 0, "errno = %d\n", errno);
1112 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1114 llapi_layout_free(layout);
1117 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) work with
1118 * non existing file. */
1119 #define T27DIR "d27"
1120 #define T27_DESC "LAYOUT_GET_EXPECTED with non existing file"
1121 #define T27_STRIPE_SIZE (1048576 * 3)
1125 struct llapi_layout *layout;
1126 const char *lfs = getenv("LFS");
1130 char dirpath[PATH_MAX];
1131 char filepath[PATH_MAX];
1134 snprintf(dirpath, sizeof(dirpath), "%s/%s", lustre_dir, T27DIR);
1135 snprintf(filepath, sizeof(filepath), "%s/nonesuch", dirpath);
1137 rc = rmdir(dirpath);
1138 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1139 rc = mkdir(dirpath, 0750);
1140 ASSERTF(rc == 0, "errno = %d", errno);
1143 lfs = "/usr/bin/lfs";
1145 snprintf(cmd, sizeof(cmd), "%s setstripe -S %d %s", lfs,
1146 T27_STRIPE_SIZE, dirpath);
1148 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1150 layout = llapi_layout_get_by_path(filepath, LAYOUT_GET_EXPECTED);
1151 ASSERTF(layout != NULL, "errno = %d\n", errno);
1153 rc = llapi_layout_stripe_count_get(layout, &count);
1154 ASSERTF(rc == 0, "errno = %d\n", errno);
1155 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1157 rc = llapi_layout_stripe_size_get(layout, &size);
1158 ASSERTF(rc == 0, "errno = %d\n", errno);
1159 ASSERTF(size == T27_STRIPE_SIZE, "size = %"PRIu64, size);
1161 rc = llapi_layout_pattern_get(layout, &pattern);
1162 ASSERTF(rc == 0, "errno = %d\n", errno);
1163 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1165 llapi_layout_free(layout);
1168 /* llapi_layout_stripe_count_get returns LLAPI_LAYOUT_WIDE for a directory
1169 * with a stripe_count of -1. */
1170 #define T28DIR "d28"
1171 #define T28_DESC "LLAPI_LAYOUT_WIDE returned as expected"
1175 struct llapi_layout *layout;
1176 const char *lfs = getenv("LFS");
1178 char dirpath[PATH_MAX];
1181 snprintf(dirpath, sizeof(dirpath), "%s/%s", lustre_dir, T28DIR);
1183 rc = rmdir(dirpath);
1184 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1185 rc = mkdir(dirpath, 0750);
1186 ASSERTF(rc == 0, "errno = %d", errno);
1189 lfs = "/usr/bin/lfs";
1191 snprintf(cmd, sizeof(cmd), "%s setstripe -c -1 %s", lfs, dirpath);
1193 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1195 layout = llapi_layout_get_by_path(dirpath, 0);
1196 ASSERTF(layout != NULL, "errno = %d\n", errno);
1198 rc = llapi_layout_stripe_count_get(layout, &count);
1199 ASSERTF(rc == 0, "errno = %d\n", errno);
1200 ASSERTF(count == LLAPI_LAYOUT_WIDE, "count = %"PRIu64"\n", count);
1202 llapi_layout_free(layout);
1205 #define T29FILE "f29"
1206 #define T29_DESC "set ost index to non-zero stripe number"
1210 uint64_t ost0, ost1, nost;
1211 struct llapi_layout *layout;
1212 char path[PATH_MAX];
1217 layout = llapi_layout_alloc();
1218 ASSERTF(layout != NULL, "errno %d", errno);
1220 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T29FILE);
1223 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1225 /* set ost index to LLAPI_LAYOUT_IDX_MAX should fail */
1226 rc = llapi_layout_ost_index_set(layout, 1, LLAPI_LAYOUT_IDX_MAX);
1227 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d\n",
1230 /* specify ost index partially */
1231 rc = llapi_layout_ost_index_set(layout, 1, 0);
1232 ASSERTF(rc == 0, "errno = %d", errno);
1234 /* create a partially specified layout will fail */
1235 fd = llapi_layout_file_create(path, 0, 0660, layout);
1236 ASSERTF(fd == -1 && errno == EINVAL, "path = %s, fd = %d, errno = %d",
1240 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1242 /* specify all stripes */
1243 rc = llapi_layout_ost_index_set(layout, 0, 1);
1244 ASSERTF(rc == 0, "errno = %d", errno);
1247 fd = llapi_layout_file_create(path, 0, 0660, layout);
1248 ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1251 ASSERTF(rc == 0, "errno = %d", errno);
1252 llapi_layout_free(layout);
1254 /* get layout from file */
1255 layout = llapi_layout_get_by_path(path, 0);
1256 ASSERTF(layout != NULL, "errno = %d", errno);
1258 rc = llapi_layout_ost_index_get(layout, 0, &ost0);
1259 ASSERTF(rc == 0, "errno = %d", errno);
1260 rc = llapi_layout_ost_index_get(layout, 1, &ost1);
1261 ASSERTF(rc == 0, "errno = %d", errno);
1262 ASSERTF(ost0 == 1, "%"PRIu64" != %d", ost0, 1);
1263 ASSERTF(ost1 == 0, "%"PRIu64" != %d", ost1, 0);
1264 llapi_layout_free(layout);
1266 /* specify more ost indexes to test realloc */
1268 layout = llapi_layout_alloc();
1269 ASSERTF(layout != NULL, "errno %d", errno);
1270 for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++) {
1271 rc = llapi_layout_ost_index_set(layout, i, nost);
1272 ASSERTF(rc == 0, "errno = %d", errno);
1273 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1274 ASSERTF(rc == 0, "errno = %d", errno);
1276 if (nost == num_osts)
1281 for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++) {
1282 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1283 ASSERTF(rc == 0, "errno = %d", errno);
1284 ASSERTF(ost0 == nost, "ost=%"PRIu64" nost=%"PRIu64"",
1287 if (nost == num_osts)
1290 llapi_layout_free(layout);
1293 layout = llapi_layout_alloc();
1294 ASSERTF(layout != NULL, "errno %d", errno);
1295 for (i = LOV_MAX_STRIPE_COUNT-1; i >= 0; i--) {
1296 rc = llapi_layout_ost_index_set(layout, i, nost);
1297 ASSERTF(rc == 0, "errno = %d", errno);
1298 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1299 ASSERTF(rc == 0, "errno = %d", errno);
1301 if (nost == num_osts)
1306 for (i = LOV_MAX_STRIPE_COUNT-1; i <= 0; i--) {
1307 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1308 ASSERTF(rc == 0, "errno = %d", errno);
1309 ASSERTF(ost0 == nost, "ost=%"PRIu64", nost=%"PRIu64"",
1312 if (nost == num_osts)
1315 llapi_layout_free(layout);
1318 #define T30FILE "f30"
1319 #define T30_DESC "create composite file, traverse components"
1323 uint64_t start[3], end[3];
1325 struct llapi_layout *layout;
1326 char path[PATH_MAX];
1329 end[0] = 64 * 1024 * 1024; /* 64m */
1331 end[1] = 1 * 1024 * 1024 * 1024; /* 1G */
1333 end[2] = LUSTRE_EOF;
1338 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T30FILE);
1341 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1343 layout = llapi_layout_alloc();
1344 ASSERTF(layout != NULL, "errno %d", errno);
1346 rc = llapi_layout_stripe_count_set(layout, 1);
1347 ASSERTF(rc == 0, "errno %d", errno);
1349 /* add component without adjusting previous component's extent
1351 rc = llapi_layout_comp_add(layout);
1352 ASSERTF(rc == -1 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1354 rc = llapi_layout_comp_extent_set(layout, start[0], end[0]);
1355 ASSERTF(rc == 0, "errno %d", errno);
1357 rc = llapi_layout_comp_add(layout);
1358 ASSERTF(rc == 0, "errno %d", errno);
1360 /* set non-contiguous extent will fail */
1361 rc = llapi_layout_comp_extent_set(layout, end[0] * 2, end[1]);
1362 ASSERTF(rc == -1 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1364 rc = llapi_layout_comp_extent_set(layout, start[1], end[1]);
1365 ASSERTF(rc == 0, "errno %d", errno);
1367 rc = llapi_layout_comp_add(layout);
1368 ASSERTF(rc == 0, "errno %d", errno);
1370 rc = llapi_layout_comp_extent_set(layout, start[2], end[2]);
1371 ASSERTF(rc == 0, "errno %d", errno);
1373 /* create composite file */
1374 fd = llapi_layout_file_create(path, 0, 0660, layout);
1375 ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1377 llapi_layout_free(layout);
1379 /* traverse & verify all components */
1380 layout = llapi_layout_get_by_path(path, 0);
1381 ASSERTF(layout != NULL, "errno = %d", errno);
1383 /* current component should be the tail component */
1384 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1385 ASSERTF(rc == 0, "errno %d", errno);
1386 ASSERTF(s == start[2] && e == end[2],
1387 "s: %"PRIu64", e: %"PRIu64"", s, e);
1389 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1390 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1392 /* delete non-tail component will fail */
1393 rc = llapi_layout_comp_del(layout);
1394 ASSERTF(rc == -1 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1396 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1397 ASSERTF(rc == 0, "errno %d", errno);
1398 ASSERTF(s == start[0] && e == end[0],
1399 "s: %"PRIu64", e: %"PRIu64"", s, e);
1401 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
1402 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1404 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1405 ASSERTF(rc == 0, "errno %d", errno);
1406 ASSERTF(s == start[1] && e == end[1],
1407 "s: %"PRIu64", e: %"PRIu64"", s, e);
1409 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
1410 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1412 rc = llapi_layout_comp_del(layout);
1413 ASSERTF(rc == 0, "errno %d", errno);
1415 llapi_layout_free(layout);
1418 #define T31FILE "f31"
1419 #define T31_DESC "add/delete component to/from existing file"
1423 uint64_t start[2], end[2];
1426 struct llapi_layout *layout;
1427 char path[PATH_MAX];
1430 end[0] = 64 * 1024 * 1024; /* 64m */
1432 end[1] = LUSTRE_EOF;
1437 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T31FILE);
1440 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1442 layout = llapi_layout_alloc();
1443 ASSERTF(layout != NULL, "errno %d", errno);
1445 rc = llapi_layout_stripe_count_set(layout, 1);
1446 ASSERTF(rc == 0, "errno %d", errno);
1448 rc = llapi_layout_comp_extent_set(layout, start[0], end[0]);
1449 ASSERTF(rc == 0, "errno %d", errno);
1451 /* create composite file */
1452 fd = llapi_layout_file_create(path, 0, 0660, layout);
1453 ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1454 llapi_layout_free(layout);
1456 layout = llapi_layout_alloc();
1457 ASSERTF(layout != NULL, "errno %d", errno);
1459 rc = llapi_layout_stripe_count_set(layout, 2);
1460 ASSERTF(rc == 0, "errno %d", errno);
1462 rc = llapi_layout_comp_extent_set(layout, start[1], end[1]);
1463 ASSERTF(rc == 0, "errno %d", errno);
1465 /* add comopnent to existing file */
1466 rc = llapi_layout_file_comp_add(path, layout);
1467 ASSERTF(rc == 0, "errno %d", errno);
1468 llapi_layout_free(layout);
1470 /* verify the composite layout after adding */
1471 layout = llapi_layout_get_by_path(path, 0);
1472 ASSERTF(layout != NULL, "errno = %d", errno);
1474 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1475 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1478 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1479 ASSERTF(rc == 0 && i < 2, "i %d, errno %d", i, errno);
1480 ASSERTF(s == start[i] && e == end[i],
1481 "i: %d s: %"PRIu64", e: %"PRIu64"", i, s, e);
1483 rc = llapi_layout_comp_id_get(layout, &id[i]);
1484 ASSERTF(rc == 0 && id[i] != 0, "i %d, errno %d, id %d",
1487 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
1488 ASSERTF(rc == 0 || i == 1, "i=%d rc=%d errno=%d", i, rc, errno);
1492 /* Verify reverse iteration gives the same IDs as forward iteration */
1493 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_LAST);
1494 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1499 rc = llapi_layout_comp_id_get(layout, &comp_id);
1500 ASSERTF(rc == 0 && comp_id == id[i],
1501 "i %d, errno %d, id[] %u/%u", i, errno, id[i], comp_id);
1503 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_PREV);
1504 ASSERTF(rc == 0 || i == 0, "i=%d rc=%d errno=%d", i, rc, errno);
1507 llapi_layout_free(layout);
1509 /* delete non-tail component will fail */
1510 rc = llapi_layout_file_comp_del(path, id[0], 0);
1511 ASSERTF(rc < 0 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1513 rc = llapi_layout_file_comp_del(path, id[1], 0);
1514 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1516 /* verify the composite layout after deleting */
1517 layout = llapi_layout_get_by_path(path, 0);
1518 ASSERTF(layout != NULL, "errno = %d", errno);
1520 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1521 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1523 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1524 ASSERTF(rc == 0, "errno %d", errno);
1525 ASSERTF(s == start[0] && e == end[0],
1526 "s: %"PRIu64", e: %"PRIu64"", s, e);
1529 #define TEST_DESC_LEN 50
1530 struct test_tbl_entry {
1531 void (*tte_fn)(void);
1532 char tte_desc[TEST_DESC_LEN];
1536 static struct test_tbl_entry test_tbl[] = {
1537 { .tte_fn = &test0, .tte_desc = T0_DESC, .tte_skip = false },
1538 { .tte_fn = &test1, .tte_desc = T1_DESC, .tte_skip = false },
1539 { .tte_fn = &test2, .tte_desc = T2_DESC, .tte_skip = false },
1540 { .tte_fn = &test3, .tte_desc = T3_DESC, .tte_skip = false },
1541 { .tte_fn = &test4, .tte_desc = T4_DESC, .tte_skip = false },
1542 { .tte_fn = &test5, .tte_desc = T5_DESC, .tte_skip = false },
1543 { .tte_fn = &test6, .tte_desc = T6_DESC, .tte_skip = false },
1544 { .tte_fn = &test7, .tte_desc = T7_DESC, .tte_skip = false },
1545 { .tte_fn = &test8, .tte_desc = T8_DESC, .tte_skip = false },
1546 { .tte_fn = &test9, .tte_desc = T9_DESC, .tte_skip = false },
1547 { .tte_fn = &test10, .tte_desc = T10_DESC, .tte_skip = false },
1548 { .tte_fn = &test11, .tte_desc = T11_DESC, .tte_skip = false },
1549 { .tte_fn = &test12, .tte_desc = T12_DESC, .tte_skip = false },
1550 { .tte_fn = &test13, .tte_desc = T13_DESC, .tte_skip = false },
1551 { .tte_fn = &test14, .tte_desc = T14_DESC, .tte_skip = false },
1552 { .tte_fn = &test15, .tte_desc = T15_DESC, .tte_skip = false },
1553 { .tte_fn = &test16, .tte_desc = T16_DESC, .tte_skip = false },
1554 { .tte_fn = &test17, .tte_desc = T17_DESC, .tte_skip = false },
1555 { .tte_fn = &test18, .tte_desc = T18_DESC, .tte_skip = false },
1556 { .tte_fn = &test19, .tte_desc = T19_DESC, .tte_skip = false },
1557 { .tte_fn = &test20, .tte_desc = T20_DESC, .tte_skip = false },
1558 { .tte_fn = &test21, .tte_desc = T21_DESC, .tte_skip = false },
1559 { .tte_fn = &test22, .tte_desc = T22_DESC, .tte_skip = false },
1560 { .tte_fn = &test23, .tte_desc = T23_DESC, .tte_skip = false },
1561 { .tte_fn = &test24, .tte_desc = T24_DESC, .tte_skip = false },
1562 { .tte_fn = &test25, .tte_desc = T25_DESC, .tte_skip = false },
1563 { .tte_fn = &test26, .tte_desc = T26_DESC, .tte_skip = false },
1564 { .tte_fn = &test27, .tte_desc = T27_DESC, .tte_skip = false },
1565 { .tte_fn = &test28, .tte_desc = T28_DESC, .tte_skip = false },
1566 { .tte_fn = &test29, .tte_desc = T29_DESC, .tte_skip = false },
1567 { .tte_fn = &test30, .tte_desc = T30_DESC, .tte_skip = false },
1568 { .tte_fn = &test31, .tte_desc = T31_DESC, .tte_skip = false },
1571 #define NUM_TESTS (sizeof(test_tbl) / sizeof(struct test_tbl_entry))
1573 void print_test_desc(int test_num, const char *test_desc, const char *status)
1577 printf(" test %2d: %s ", test_num, test_desc);
1578 for (i = 0; i < TEST_DESC_LEN - strlen(test_desc); i++)
1580 printf(" %s\n", status);
1583 /* This function runs a single test by forking the process. This way,
1584 * if there is a segfault during a test, the test program won't crash. */
1585 int test(void (*test_fn)(), const char *test_desc, bool test_skip, int test_num)
1589 char status_buf[128];
1592 print_test_desc(test_num, test_desc, "skip");
1598 ERROR("cannot fork: %s", strerror(errno));
1599 } else if (pid > 0) {
1602 /* Non-zero value indicates failure. */
1605 strncpy(status_buf, "pass", sizeof(status_buf));
1606 } else if WIFSIGNALED(status) {
1607 snprintf(status_buf, sizeof(status_buf),
1608 "fail (exit status %d, killed by SIG%d)",
1609 WEXITSTATUS(status), WTERMSIG(status));
1612 snprintf(status_buf, sizeof(status_buf),
1613 "fail (exit status %d)", WEXITSTATUS(status));
1616 print_test_desc(test_num, test_desc, status_buf);
1617 } else if (pid == 0) {
1618 /* Run the test in the child process. Exit with 0 for success,
1619 * non-zero for failure */
1627 /* 'str_tests' are the tests to be skipped, such as "1,3,4,.." */
1628 static void set_tests_skipped(char *str_tests)
1630 char *ptr = str_tests;
1633 if (ptr == NULL || strlen(ptr) == 0)
1636 while (*ptr != '\0') {
1637 tstno = strtoul(ptr, &ptr, 0);
1638 if (tstno >= 0 && tstno < NUM_TESTS)
1639 test_tbl[tstno].tte_skip = true;
1647 static void process_args(int argc, char *argv[])
1651 while ((c = getopt(argc, argv, "d:p:o:s:")) != -1) {
1654 lustre_dir = optarg;
1660 num_osts = atoi(optarg);
1663 set_tests_skipped(optarg);
1666 fprintf(stderr, "Unknown option '%c'\n", optopt);
1672 int main(int argc, char *argv[])
1679 llapi_msg_set_level(LLAPI_MSG_OFF);
1681 process_args(argc, argv);
1682 if (lustre_dir == NULL)
1683 lustre_dir = "/mnt/lustre";
1684 if (poolname == NULL)
1685 poolname = "testpool";
1690 DIE("Error: at least 2 OSTS are required\n");
1692 if (stat(lustre_dir, &s) < 0)
1693 DIE("cannot stat %s: %s\n", lustre_dir, strerror(errno));
1694 else if (!S_ISDIR(s.st_mode))
1695 DIE("%s: not a directory\n", lustre_dir);
1697 rc = llapi_search_fsname(lustre_dir, fsname);
1699 fprintf(stderr, "Error: %s: not a Lustre filesystem\n",
1704 /* Play nice with Lustre test scripts. Non-line buffered output
1705 * stream under I/O redirection may appear incorrectly. */
1706 setvbuf(stdout, NULL, _IOLBF, 0);
1708 for (i = 0; i < NUM_TESTS; i++) {
1709 struct test_tbl_entry *tst = &test_tbl[i];
1710 if (test(tst->tte_fn, tst->tte_desc, tst->tte_skip, i) != 0)