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>
53 #define ERROR(fmt, ...) \
54 fprintf(stderr, "%s: %s:%d: %s: " fmt "\n", \
55 program_invocation_short_name, __FILE__, __LINE__, \
56 __func__, ## __VA_ARGS__);
58 #define DIE(fmt, ...) \
60 ERROR(fmt, ## __VA_ARGS__); \
64 #define ASSERTF(cond, fmt, ...) \
67 DIE("assertion '%s' failed: "fmt, #cond, ## __VA_ARGS__);\
70 static char *lustre_dir;
71 static char *poolname;
72 static int num_osts = -1;
74 void usage(char *prog)
76 printf("Usage: %s [-d lustre_dir] [-p pool_name] [-o num_osts] "
77 "[-s $n,$m,..]\n", prog);
82 #define T0_STRIPE_COUNT num_osts
83 #define T0_STRIPE_SIZE 1048576
84 #define T0_OST_OFFSET (num_osts - 1)
85 #define T0_DESC "Read/write layout attributes then create a file"
92 struct llapi_layout *layout = llapi_layout_alloc();
94 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
96 ASSERTF(layout != NULL, "errno %d", errno);
98 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
101 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
104 rc = llapi_layout_stripe_count_set(layout, T0_STRIPE_COUNT);
105 ASSERTF(rc == 0, "errno = %d", errno);
106 rc = llapi_layout_stripe_count_get(layout, &count);
107 ASSERTF(rc == 0 && count == T0_STRIPE_COUNT, "%"PRIu64" != %d", count,
111 rc = llapi_layout_stripe_size_set(layout, T0_STRIPE_SIZE);
112 ASSERTF(rc == 0, "errno = %d", errno);
113 rc = llapi_layout_stripe_size_get(layout, &size);
114 ASSERTF(rc == 0 && size == T0_STRIPE_SIZE, "%"PRIu64" != %d", size,
118 rc = llapi_layout_pool_name_set(layout, poolname);
119 ASSERTF(rc == 0, "errno = %d", errno);
120 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
121 ASSERTF(rc == 0, "errno = %d", errno);
122 rc = strcmp(mypool, poolname);
123 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
126 rc = llapi_layout_ost_index_set(layout, 0, T0_OST_OFFSET);
127 ASSERTF(rc == 0, "errno = %d", errno);
130 fd = llapi_layout_file_create(path, 0, 0660, layout);
131 ASSERTF(fd >= 0, "path = %s, errno = %d", path, errno);
133 ASSERTF(rc == 0, "errno = %d", errno);
134 llapi_layout_free(layout);
137 void __test1_helper(struct llapi_layout *layout)
144 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
146 rc = llapi_layout_stripe_count_get(layout, &count);
147 ASSERTF(count == T0_STRIPE_COUNT, "%"PRIu64" != %d", count,
150 rc = llapi_layout_stripe_size_get(layout, &size);
151 ASSERTF(size == T0_STRIPE_SIZE, "%"PRIu64" != %d", size,
154 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
155 ASSERTF(rc == 0, "errno = %d", errno);
156 rc = strcmp(mypool, poolname);
157 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
159 rc = llapi_layout_ost_index_get(layout, 0, &ost0);
160 ASSERTF(rc == 0, "errno = %d", errno);
161 rc = llapi_layout_ost_index_get(layout, 1, &ost1);
162 ASSERTF(rc == 0, "errno = %d", errno);
163 ASSERTF(ost0 == T0_OST_OFFSET, "%"PRIu64" != %d", ost0, T0_OST_OFFSET);
164 ASSERTF(ost1 != ost0, "%"PRIu64" == %"PRIu64, ost0, ost1);
167 #define T1_DESC "Read test0 file by path and verify attributes"
172 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
173 struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
174 ASSERTF(layout != NULL, "errno = %d", errno);
175 __test1_helper(layout);
176 llapi_layout_free(layout);
179 #define T2_DESC "Read test0 file by FD and verify attributes"
186 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
188 fd = open(path, O_RDONLY);
189 ASSERTF(fd >= 0, "open(%s): errno = %d", path, errno);
191 struct llapi_layout *layout = llapi_layout_get_by_fd(fd, 0);
192 ASSERTF(layout != NULL, "errno = %d", errno);
195 ASSERTF(rc == 0, "close(%s): errno = %d", path, errno);
197 __test1_helper(layout);
198 llapi_layout_free(layout);
201 #define T3_DESC "Read test0 file by FID and verify attributes"
205 struct llapi_layout *layout;
210 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
212 rc = llapi_path2fid(path, &fid);
213 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
214 snprintf(fidstr, sizeof(fidstr), "0x%"PRIx64":0x%x:0x%x",
215 (uint64_t)fid.f_seq, fid.f_oid, fid.f_ver);
217 layout = llapi_layout_get_by_fid(path, &fid, 0);
218 ASSERTF(layout != NULL, "fidstr = %s, errno = %d", fidstr, errno);
220 __test1_helper(layout);
221 llapi_layout_free(layout);
225 #define T4_STRIPE_COUNT 2
226 #define T4_STRIPE_SIZE 2097152
227 #define T4_DESC "Verify compatibility with 'lfs setstripe'"
235 const char *lfs = getenv("LFS");
236 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
240 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T4FILE);
243 lfs = "/usr/bin/lfs";
246 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
248 snprintf(cmd, sizeof(cmd), "%s setstripe %s %s -c %d -S %d %s", lfs,
249 strlen(poolname) > 0 ? "-p" : "", poolname, T4_STRIPE_COUNT,
250 T4_STRIPE_SIZE, path);
252 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
255 struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
256 ASSERTF(layout != NULL, "errno = %d", errno);
258 rc = llapi_layout_stripe_count_get(layout, &count);
259 ASSERTF(count == T4_STRIPE_COUNT, "%"PRIu64" != %d", count,
262 rc = llapi_layout_stripe_size_get(layout, &size);
263 ASSERTF(size == T4_STRIPE_SIZE, "%"PRIu64" != %d", size,
266 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
267 ASSERTF(rc == 0, "errno = %d", errno);
268 rc = strcmp(mypool, poolname);
269 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
271 rc = llapi_layout_ost_index_get(layout, 0, &ost0);
272 ASSERTF(rc == 0, "errno = %d", errno);
273 rc = llapi_layout_ost_index_get(layout, 1, &ost1);
274 ASSERTF(rc == 0, "errno = %d", errno);
275 ASSERTF(ost1 != ost0, "%"PRIu64" == %"PRIu64, ost0, ost1);
277 llapi_layout_free(layout);
281 #define T5_DESC "llapi_layout_get_by_path ENOENT handling"
286 struct llapi_layout *layout;
288 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T5FILE);
291 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
294 layout = llapi_layout_get_by_path(path, 0);
295 ASSERTF(layout == NULL && errno == ENOENT, "errno = %d", errno);
298 #define T6_DESC "llapi_layout_get_by_fd EBADF handling"
302 struct llapi_layout *layout = llapi_layout_get_by_fd(9999, 0);
303 ASSERTF(layout == NULL && errno == EBADF, "errno = %d", errno);
307 #define T7_DESC "llapi_layout_get_by_path EACCES handling"
312 uid_t myuid = getuid();
314 const char *runas = getenv("RUNAS_ID");
318 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T7FILE);
319 ASSERTF(myuid == 0, "myuid = %d", myuid); /* Need root for this test. */
321 /* Create file as root */
323 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
325 fd = open(path, O_CREAT, 0400);
326 ASSERTF(fd > 0, "errno = %d", errno);
328 ASSERTF(rc == 0, "errno = %d", errno);
330 /* Become unprivileged user */
333 ASSERTF(uid != 0, "runas = %s", runas);
335 pw = getpwnam("nobody");
336 ASSERTF(pw != NULL, "errno = %d", errno);
340 ASSERTF(rc == 0, "errno = %d", errno);
342 struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
343 ASSERTF(layout == NULL && errno == EACCES, "errno = %d", errno);
345 ASSERTF(rc == 0, "errno = %d", errno);
348 /* llapi_layout_get_by_path() returns default layout for file with no
349 * striping attributes. */
351 #define T8_DESC "llapi_layout_get_by_path ENODATA handling"
356 struct llapi_layout *layout;
362 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T8FILE);
365 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
366 fd = open(path, O_CREAT, 0640);
367 ASSERTF(fd >= 0, "errno = %d", errno);
369 ASSERTF(rc == 0, "errno = %d", errno);
371 layout = llapi_layout_get_by_path(path, 0);
372 ASSERTF(layout != NULL, "errno = %d\n", errno);
374 rc = llapi_layout_stripe_count_get(layout, &count);
375 ASSERTF(rc == 0, "errno = %d\n", errno);
376 ASSERTF(count == LLAPI_LAYOUT_DEFAULT, "count = %"PRIu64"\n", count);
378 rc = llapi_layout_stripe_size_get(layout, &size);
379 ASSERTF(rc == 0, "errno = %d\n", errno);
380 ASSERTF(size == LLAPI_LAYOUT_DEFAULT, "size = %"PRIu64"\n", size);
382 rc = llapi_layout_pattern_get(layout, &pattern);
383 ASSERTF(rc == 0, "errno = %d\n", errno);
384 ASSERTF(pattern == LLAPI_LAYOUT_DEFAULT, "pattern = %"PRIu64"\n",
387 llapi_layout_free(layout);
390 /* Verify llapi_layout_patter_set() return values for various inputs. */
391 #define T9_DESC "verify llapi_layout_pattern_set() return values"
394 struct llapi_layout *layout;
397 layout = llapi_layout_alloc();
398 ASSERTF(layout != NULL, "errno = %d\n", errno);
401 rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_INVALID);
402 ASSERTF(rc == -1 && errno == EOPNOTSUPP, "rc = %d, errno = %d", rc,
406 rc = llapi_layout_pattern_set(NULL, LLAPI_LAYOUT_DEFAULT);
407 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc,
411 rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_DEFAULT);
412 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
415 rc = llapi_layout_pattern_set(layout, LLAPI_LAYOUT_RAID0);
416 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
418 llapi_layout_free(layout);
421 /* Verify stripe_count interfaces return errors as expected */
422 #define T10_DESC "stripe_count error handling"
427 struct llapi_layout *layout;
429 layout = llapi_layout_alloc();
430 ASSERTF(layout != NULL, "errno = %d", errno);
432 /* invalid stripe count */
434 rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_INVALID);
435 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
438 rc = llapi_layout_stripe_count_set(layout, -1);
439 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
443 rc = llapi_layout_stripe_count_set(NULL, 2);
444 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
448 rc = llapi_layout_stripe_count_get(NULL, &count);
449 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
453 rc = llapi_layout_stripe_count_get(layout, NULL);
454 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
456 /* stripe count too large */
458 rc = llapi_layout_stripe_count_set(layout, LOV_MAX_STRIPE_COUNT + 1);
459 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
460 llapi_layout_free(layout);
463 /* Verify stripe_size interfaces return errors as expected */
464 #define T11_DESC "stripe_size error handling"
469 struct llapi_layout *layout;
471 layout = llapi_layout_alloc();
472 ASSERTF(layout != NULL, "errno = %d", errno);
474 /* negative stripe size */
476 rc = llapi_layout_stripe_size_set(layout, -1);
477 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
479 /* invalid stripe size */
481 rc = llapi_layout_stripe_size_set(layout, LLAPI_LAYOUT_INVALID);
482 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
484 /* stripe size too big */
486 rc = llapi_layout_stripe_size_set(layout, (1ULL << 33));
487 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
491 rc = llapi_layout_stripe_size_set(NULL, 1048576);
492 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
495 rc = llapi_layout_stripe_size_get(NULL, &size);
496 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
500 rc = llapi_layout_stripe_size_get(layout, NULL);
501 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
503 llapi_layout_free(layout);
506 /* Verify pool_name interfaces return errors as expected */
507 #define T12_DESC "pool_name error handling"
511 struct llapi_layout *layout;
512 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
514 layout = llapi_layout_alloc();
515 ASSERTF(layout != NULL, "errno = %d", errno);
519 rc = llapi_layout_pool_name_set(NULL, "foo");
520 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
524 rc = llapi_layout_pool_name_set(layout, NULL);
525 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
529 rc = llapi_layout_pool_name_get(NULL, mypool, sizeof(mypool));
530 ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
534 rc = llapi_layout_pool_name_get(layout, NULL, sizeof(mypool));
535 ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
537 /* Pool name too long*/
539 rc = llapi_layout_pool_name_set(layout, "0123456789abcdef");
540 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
542 llapi_layout_free(layout);
545 /* Verify ost_index interface returns errors as expected */
546 #define T13FILE "t13"
547 #define T13_STRIPE_COUNT 2
548 #define T13_DESC "ost_index error handling"
554 struct llapi_layout *layout;
557 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T13FILE);
559 layout = llapi_layout_alloc();
560 ASSERTF(layout != NULL, "errno = %d", errno);
562 /* invalid OST index */
564 rc = llapi_layout_ost_index_set(layout, 0, LLAPI_LAYOUT_INVALID);
565 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
568 rc = llapi_layout_ost_index_set(layout, 0, -1);
569 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
573 rc = llapi_layout_ost_index_set(NULL, 0, 1);
574 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
577 rc = llapi_layout_ost_index_get(NULL, 0, &idx);
578 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
582 rc = llapi_layout_ost_index_get(layout, 0, NULL);
583 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
585 /* Layout not read from file so has no OST data. */
587 rc = llapi_layout_stripe_count_set(layout, T13_STRIPE_COUNT);
588 ASSERTF(rc == 0, "errno = %d", errno);
589 rc = llapi_layout_ost_index_get(layout, 0, &idx);
590 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
592 /* n greater than stripe count*/
594 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
595 rc = llapi_layout_stripe_count_set(layout, T13_STRIPE_COUNT);
596 ASSERTF(rc == 0, "errno = %d", errno);
597 fd = llapi_layout_file_create(path, 0, 0644, layout);
598 ASSERTF(fd >= 0, "errno = %d", errno);
600 ASSERTF(rc == 0, "errno = %d", errno);
601 llapi_layout_free(layout);
603 layout = llapi_layout_get_by_path(path, 0);
604 ASSERTF(layout != NULL, "errno = %d", errno);
606 rc = llapi_layout_ost_index_get(layout, T13_STRIPE_COUNT + 1, &idx);
607 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
609 llapi_layout_free(layout);
612 /* Verify llapi_layout_file_create() returns errors as expected */
613 #define T14_DESC "llapi_layout_file_create error handling"
617 struct llapi_layout *layout = llapi_layout_alloc();
621 rc = llapi_layout_file_create(NULL, 0, 0, layout);
622 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
624 llapi_layout_free(layout);
627 /* Can't change striping attributes of existing file. */
628 #define T15FILE "t15"
629 #define T15_STRIPE_COUNT 2
630 #define T15_DESC "Can't change striping attributes of existing file"
636 struct llapi_layout *layout;
639 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T15FILE);
642 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
644 layout = llapi_layout_alloc();
645 ASSERTF(layout != NULL, "errno = %d", errno);
646 rc = llapi_layout_stripe_count_set(layout, T15_STRIPE_COUNT);
647 ASSERTF(rc == 0, "errno = %d", errno);
650 fd = llapi_layout_file_create(path, 0, 0640, layout);
651 ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
653 ASSERTF(rc == 0, "errno = %d", errno);
655 rc = llapi_layout_stripe_count_set(layout, T15_STRIPE_COUNT - 1);
657 fd = llapi_layout_file_open(path, 0, 0640, layout);
658 ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
660 ASSERTF(rc == 0, "errno = %d", errno);
661 llapi_layout_free(layout);
663 layout = llapi_layout_get_by_path(path, 0);
664 ASSERTF(layout != NULL, "errno = %d", errno);
665 rc = llapi_layout_stripe_count_get(layout, &count);
666 ASSERTF(rc == 0 && count == T15_STRIPE_COUNT,
667 "rc = %d, %"PRIu64" != %d", rc, count, T15_STRIPE_COUNT);
668 llapi_layout_free(layout);
671 /* Default stripe attributes are applied as expected. */
672 #define T16FILE "t16"
673 #define T16_DESC "Default stripe attributes are applied as expected"
678 struct llapi_layout *deflayout;
679 struct llapi_layout *filelayout;
686 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T16FILE);
689 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
691 deflayout = llapi_layout_get_by_path(lustre_dir, LAYOUT_GET_EXPECTED);
692 ASSERTF(deflayout != NULL, "errno = %d", errno);
693 rc = llapi_layout_stripe_size_get(deflayout, &dsize);
694 ASSERTF(rc == 0, "errno = %d", errno);
695 rc = llapi_layout_stripe_count_get(deflayout, &dcount);
696 ASSERTF(rc == 0, "errno = %d", errno);
698 /* First, with a default struct llapi_layout */
699 filelayout = llapi_layout_alloc();
700 ASSERTF(filelayout != NULL, "errno = %d", errno);
702 fd = llapi_layout_file_create(path, 0, 0640, filelayout);
703 ASSERTF(fd >= 0, "errno = %d", errno);
706 ASSERTF(rc == 0, "errno = %d", errno);
708 llapi_layout_free(filelayout);
710 filelayout = llapi_layout_get_by_path(path, 0);
711 ASSERTF(filelayout != NULL, "errno = %d", errno);
713 rc = llapi_layout_stripe_count_get(filelayout, &fcount);
714 ASSERTF(rc == 0, "errno = %d", errno);
715 ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
716 dcount == LLAPI_LAYOUT_WIDE,
717 "%"PRIu64" != %"PRIu64, fcount, dcount);
719 rc = llapi_layout_stripe_size_get(filelayout, &fsize);
720 ASSERTF(rc == 0, "errno = %d", errno);
721 ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
723 /* NULL layout also implies default layout */
725 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
727 fd = llapi_layout_file_create(path, 0, 0640, filelayout);
728 ASSERTF(fd >= 0, "errno = %d", errno);
730 ASSERTF(rc == 0, "errno = %d", errno);
731 filelayout = llapi_layout_get_by_path(path, 0);
732 ASSERTF(filelayout != NULL, "errno = %d", errno);
734 rc = llapi_layout_stripe_count_get(filelayout, &fcount);
735 ASSERTF(rc == 0, "errno = %d", errno);
736 rc = llapi_layout_stripe_size_get(filelayout, &fsize);
737 ASSERTF(rc == 0, "errno = %d", errno);
738 ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
739 dcount == LLAPI_LAYOUT_WIDE,
740 "%"PRIu64" != %"PRIu64, fcount, dcount);
741 ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
743 llapi_layout_free(filelayout);
744 llapi_layout_free(deflayout);
747 /* Setting stripe count to LLAPI_LAYOUT_WIDE uses all available OSTs. */
748 #define T17FILE "t17"
749 #define T17_DESC "LLAPI_LAYOUT_WIDE is honored"
755 uint64_t osts_layout;
756 struct llapi_layout *layout;
759 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T17FILE);
762 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
763 layout = llapi_layout_alloc();
764 ASSERTF(layout != NULL, "errno = %d", errno);
765 rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_WIDE);
766 ASSERTF(rc == 0, "errno = %d", errno);
767 fd = llapi_layout_file_create(path, 0, 0640, layout);
768 ASSERTF(fd >= 0, "errno = %d", errno);
770 ASSERTF(rc == 0, "errno = %d", errno);
771 llapi_layout_free(layout);
773 /* Get number of available OSTs */
774 fd = open(path, O_RDONLY);
775 ASSERTF(fd >= 0, "errno = %d", errno);
776 rc = llapi_lov_get_uuids(fd, NULL, &osts_all);
777 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
779 ASSERTF(rc == 0, "errno = %d", errno);
781 layout = llapi_layout_get_by_path(path, 0);
782 ASSERTF(layout != NULL, "errno = %d", errno);
783 rc = llapi_layout_stripe_count_get(layout, &osts_layout);
784 ASSERTF(osts_layout == osts_all, "%"PRIu64" != %d", osts_layout,
787 llapi_layout_free(layout);
790 /* Setting pool with "fsname.pool" notation. */
791 #define T18FILE "t18"
792 #define T18_DESC "Setting pool with fsname.pool notation"
797 struct llapi_layout *layout = llapi_layout_alloc();
799 char pool[LOV_MAXPOOLNAME*2 + 1];
800 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
802 snprintf(pool, sizeof(pool), "lustre.%s", poolname);
804 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T18FILE);
806 ASSERTF(layout != NULL, "errno = %d", errno);
809 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
811 rc = llapi_layout_pool_name_set(layout, pool);
812 ASSERTF(rc == 0, "errno = %d", errno);
814 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
815 ASSERTF(rc == 0, "errno = %d", errno);
816 rc = strcmp(mypool, poolname);
817 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
818 fd = llapi_layout_file_create(path, 0, 0640, layout);
819 ASSERTF(fd >= 0, "errno = %d", errno);
821 ASSERTF(rc == 0, "errno = %d", errno);
823 llapi_layout_free(layout);
825 layout = llapi_layout_get_by_path(path, 0);
826 ASSERTF(layout != NULL, "errno = %d", errno);
827 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
828 ASSERTF(rc == 0, "errno = %d", errno);
829 rc = strcmp(mypool, poolname);
830 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
831 llapi_layout_free(layout);
834 #define T19_DESC "Maximum length pool name is NULL-terminated"
837 struct llapi_layout *layout;
838 char *name = "0123456789abcde";
839 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
842 layout = llapi_layout_alloc();
843 ASSERTF(layout != NULL, "errno = %d", errno);
844 rc = llapi_layout_pool_name_set(layout, name);
845 ASSERTF(rc == 0, "errno = %d", errno);
846 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
847 ASSERTF(strlen(name) == strlen(mypool), "name = %s, str = %s", name,
849 llapi_layout_free(layout);
852 #define T20FILE "t20"
853 #define T20_DESC "LLAPI_LAYOUT_DEFAULT is honored"
858 struct llapi_layout *deflayout;
859 struct llapi_layout *filelayout;
866 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T20FILE);
869 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
871 filelayout = llapi_layout_alloc();
872 ASSERTF(filelayout != NULL, "errno = %d", errno);
874 rc = llapi_layout_stripe_size_set(filelayout, LLAPI_LAYOUT_DEFAULT);
875 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
877 rc = llapi_layout_stripe_count_set(filelayout, LLAPI_LAYOUT_DEFAULT);
878 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
880 fd = llapi_layout_file_create(path, 0, 0640, filelayout);
881 ASSERTF(fd >= 0, "errno = %d", errno);
884 ASSERTF(rc == 0, "errno = %d", errno);
886 llapi_layout_free(filelayout);
888 deflayout = llapi_layout_get_by_path(lustre_dir, LAYOUT_GET_EXPECTED);
889 ASSERTF(deflayout != NULL, "errno = %d", errno);
891 filelayout = llapi_layout_get_by_path(path, 0);
892 ASSERTF(filelayout != NULL, "errno = %d", errno);
894 rc = llapi_layout_stripe_count_get(filelayout, &fcount);
895 ASSERTF(rc == 0, "errno = %d", errno);
896 rc = llapi_layout_stripe_count_get(deflayout, &dcount);
897 ASSERTF(rc == 0, "errno = %d", errno);
898 ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
899 dcount == LLAPI_LAYOUT_WIDE,
900 "%"PRIu64" != %"PRIu64, fcount, dcount);
902 rc = llapi_layout_stripe_size_get(filelayout, &fsize);
903 ASSERTF(rc == 0, "errno = %d", errno);
904 rc = llapi_layout_stripe_size_get(deflayout, &dsize);
905 ASSERTF(rc == 0, "errno = %d", errno);
906 ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
908 llapi_layout_free(filelayout);
909 llapi_layout_free(deflayout);
912 #define T21_DESC "llapi_layout_file_create fails for non-Lustre file"
915 struct llapi_layout *layout;
916 char template[PATH_MAX];
920 snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
921 fd = mkstemp(template);
922 ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
924 ASSERTF(rc == 0, "errno = %d", fd);
925 rc = unlink(template);
926 ASSERTF(rc == 0, "errno = %d", errno);
928 layout = llapi_layout_alloc();
929 ASSERTF(layout != NULL, "errno = %d", errno);
931 fd = llapi_layout_file_create(template, 0, 0640, layout);
932 ASSERTF(fd == -1 && errno == ENOTTY,
933 "fd = %d, errno = %d, template = %s", fd, errno, template);
934 llapi_layout_free(layout);
937 #define T22FILE "t22"
938 #define T22_DESC "llapi_layout_file_create applied mode correctly"
945 mode_t mode_in = 0640;
949 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T22FILE);
952 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
954 umask_orig = umask(S_IWGRP | S_IWOTH);
956 fd = llapi_layout_file_create(path, 0, mode_in, NULL);
957 ASSERTF(fd >= 0, "errno = %d", errno);
959 (void) umask(umask_orig);
962 ASSERTF(rc == 0, "errno = %d", errno);
965 ASSERTF(rc == 0, "errno = %d", fd);
967 mode_out = st.st_mode & ~S_IFMT;
968 ASSERTF(mode_in == mode_out, "%o != %o", mode_in, mode_out);
971 #define T23_DESC "llapi_layout_get_by_path fails for non-Lustre file"
974 struct llapi_layout *layout;
975 char template[PATH_MAX];
979 snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
980 fd = mkstemp(template);
981 ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
983 ASSERTF(rc == 0, "errno = %d", fd);
985 layout = llapi_layout_get_by_path(template, 0);
986 ASSERTF(layout == NULL && errno == ENOTTY,
987 "errno = %d, template = %s", errno, template);
989 rc = unlink(template);
990 ASSERTF(rc == 0, "errno = %d", errno);
993 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
994 * for file with unspecified layout. */
995 #define T24FILE "t24"
996 #define T24_DESC "LAYOUT_GET_EXPECTED works with existing file"
1001 struct llapi_layout *layout;
1005 char path[PATH_MAX];
1007 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T24FILE);
1010 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1011 fd = open(path, O_CREAT, 0640);
1012 ASSERTF(fd >= 0, "errno = %d", errno);
1014 ASSERTF(rc == 0, "errno = %d", errno);
1016 layout = llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED);
1017 ASSERTF(layout != NULL, "errno = %d\n", errno);
1019 rc = llapi_layout_stripe_count_get(layout, &count);
1020 ASSERTF(rc == 0, "errno = %d\n", errno);
1021 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1023 rc = llapi_layout_stripe_size_get(layout, &size);
1024 ASSERTF(rc == 0, "errno = %d\n", errno);
1025 ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1027 rc = llapi_layout_pattern_get(layout, &pattern);
1028 ASSERTF(rc == 0, "errno = %d\n", errno);
1029 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1031 llapi_layout_free(layout);
1034 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
1035 * for directory with unspecified layout. */
1036 #define T25DIR "d25"
1037 #define T25_DESC "LAYOUT_GET_EXPECTED works with directory"
1041 struct llapi_layout *layout;
1047 snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T25DIR);
1050 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1051 rc = mkdir(dir, 0750);
1052 ASSERTF(rc == 0, "errno = %d", errno);
1054 layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1055 ASSERTF(layout != NULL, "errno = %d\n", errno);
1057 rc = llapi_layout_stripe_count_get(layout, &count);
1058 ASSERTF(rc == 0, "errno = %d\n", errno);
1059 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1061 rc = llapi_layout_stripe_size_get(layout, &size);
1062 ASSERTF(rc == 0, "errno = %d\n", errno);
1063 ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1065 rc = llapi_layout_pattern_get(layout, &pattern);
1066 ASSERTF(rc == 0, "errno = %d\n", errno);
1067 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1069 llapi_layout_free(layout);
1072 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) correctly combines
1073 * specified attributes of parent directory with attributes filesystem root. */
1074 #define T26DIR "d26"
1075 #define T26_DESC "LAYOUT_GET_EXPECTED partially specified parent"
1076 #define T26_STRIPE_SIZE (1048576 * 4)
1080 struct llapi_layout *layout;
1081 const char *lfs = getenv("LFS");
1088 snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T26DIR);
1090 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1091 rc = mkdir(dir, 0750);
1092 ASSERTF(rc == 0, "errno = %d", errno);
1095 lfs = "/usr/bin/lfs";
1097 snprintf(cmd, sizeof(cmd), "%s setstripe -S %d %s", lfs,
1098 T26_STRIPE_SIZE, dir);
1100 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1102 layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1103 ASSERTF(layout != NULL, "errno = %d\n", errno);
1105 rc = llapi_layout_stripe_count_get(layout, &count);
1106 ASSERTF(rc == 0, "errno = %d\n", errno);
1107 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1109 rc = llapi_layout_stripe_size_get(layout, &size);
1110 ASSERTF(rc == 0, "errno = %d\n", errno);
1111 ASSERTF(size == T26_STRIPE_SIZE, "size = %"PRIu64, size);
1113 rc = llapi_layout_pattern_get(layout, &pattern);
1114 ASSERTF(rc == 0, "errno = %d\n", errno);
1115 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1117 llapi_layout_free(layout);
1120 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) work with
1121 * non existing file. */
1122 #define T27DIR "d27"
1123 #define T27_DESC "LAYOUT_GET_EXPECTED with non existing file"
1124 #define T27_STRIPE_SIZE (1048576 * 3)
1128 struct llapi_layout *layout;
1129 const char *lfs = getenv("LFS");
1133 char dirpath[PATH_MAX];
1134 char filepath[PATH_MAX];
1137 snprintf(dirpath, sizeof(dirpath), "%s/%s", lustre_dir, T27DIR);
1138 snprintf(filepath, sizeof(filepath), "%s/nonesuch", dirpath);
1140 rc = rmdir(dirpath);
1141 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1142 rc = mkdir(dirpath, 0750);
1143 ASSERTF(rc == 0, "errno = %d", errno);
1146 lfs = "/usr/bin/lfs";
1148 snprintf(cmd, sizeof(cmd), "%s setstripe -S %d %s", lfs,
1149 T27_STRIPE_SIZE, dirpath);
1151 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1153 layout = llapi_layout_get_by_path(filepath, LAYOUT_GET_EXPECTED);
1154 ASSERTF(layout != NULL, "errno = %d\n", errno);
1156 rc = llapi_layout_stripe_count_get(layout, &count);
1157 ASSERTF(rc == 0, "errno = %d\n", errno);
1158 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1160 rc = llapi_layout_stripe_size_get(layout, &size);
1161 ASSERTF(rc == 0, "errno = %d\n", errno);
1162 ASSERTF(size == T27_STRIPE_SIZE, "size = %"PRIu64, size);
1164 rc = llapi_layout_pattern_get(layout, &pattern);
1165 ASSERTF(rc == 0, "errno = %d\n", errno);
1166 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1168 llapi_layout_free(layout);
1171 /* llapi_layout_stripe_count_get returns LLAPI_LAYOUT_WIDE for a directory
1172 * with a stripe_count of -1. */
1173 #define T28DIR "d28"
1174 #define T28_DESC "LLAPI_LAYOUT_WIDE returned as expected"
1178 struct llapi_layout *layout;
1179 const char *lfs = getenv("LFS");
1181 char dirpath[PATH_MAX];
1184 snprintf(dirpath, sizeof(dirpath), "%s/%s", lustre_dir, T28DIR);
1186 rc = rmdir(dirpath);
1187 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1188 rc = mkdir(dirpath, 0750);
1189 ASSERTF(rc == 0, "errno = %d", errno);
1192 lfs = "/usr/bin/lfs";
1194 snprintf(cmd, sizeof(cmd), "%s setstripe -c -1 %s", lfs, dirpath);
1196 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1198 layout = llapi_layout_get_by_path(dirpath, 0);
1199 ASSERTF(layout != NULL, "errno = %d\n", errno);
1201 rc = llapi_layout_stripe_count_get(layout, &count);
1202 ASSERTF(rc == 0, "errno = %d\n", errno);
1203 ASSERTF(count == LLAPI_LAYOUT_WIDE, "count = %"PRIu64"\n", count);
1205 llapi_layout_free(layout);
1208 #define T29FILE "f29"
1209 #define T29_DESC "set ost index to non-zero stripe number"
1213 uint64_t ost0, ost1, nost;
1214 struct llapi_layout *layout;
1215 char path[PATH_MAX];
1220 layout = llapi_layout_alloc();
1221 ASSERTF(layout != NULL, "errno %d", errno);
1223 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T29FILE);
1226 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1228 /* set ost index to LLAPI_LAYOUT_IDX_MAX should fail */
1229 rc = llapi_layout_ost_index_set(layout, 1, LLAPI_LAYOUT_IDX_MAX);
1230 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d\n",
1233 /* specify ost index partially */
1234 rc = llapi_layout_ost_index_set(layout, 1, 0);
1235 ASSERTF(rc == 0, "errno = %d", errno);
1237 /* create a partially specified layout will fail */
1238 fd = llapi_layout_file_create(path, 0, 0660, layout);
1239 ASSERTF(fd == -1 && errno == EINVAL, "path = %s, fd = %d, errno = %d",
1243 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1245 /* specify all stripes */
1246 rc = llapi_layout_ost_index_set(layout, 0, 1);
1247 ASSERTF(rc == 0, "errno = %d", errno);
1250 fd = llapi_layout_file_create(path, 0, 0660, layout);
1251 ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1254 ASSERTF(rc == 0, "errno = %d", errno);
1255 llapi_layout_free(layout);
1257 /* get layout from file */
1258 layout = llapi_layout_get_by_path(path, 0);
1259 ASSERTF(layout != NULL, "errno = %d", errno);
1261 rc = llapi_layout_ost_index_get(layout, 0, &ost0);
1262 ASSERTF(rc == 0, "errno = %d", errno);
1263 rc = llapi_layout_ost_index_get(layout, 1, &ost1);
1264 ASSERTF(rc == 0, "errno = %d", errno);
1265 ASSERTF(ost0 == 1, "%"PRIu64" != %d", ost0, 1);
1266 ASSERTF(ost1 == 0, "%"PRIu64" != %d", ost1, 0);
1267 llapi_layout_free(layout);
1269 /* specify more ost indexes to test realloc */
1271 layout = llapi_layout_alloc();
1272 ASSERTF(layout != NULL, "errno %d", errno);
1273 for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++) {
1274 rc = llapi_layout_ost_index_set(layout, i, nost);
1275 ASSERTF(rc == 0, "errno = %d", errno);
1276 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1277 ASSERTF(rc == 0, "errno = %d", errno);
1279 if (nost == num_osts)
1284 for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++) {
1285 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1286 ASSERTF(rc == 0, "errno = %d", errno);
1287 ASSERTF(ost0 == nost, "ost=%"PRIu64" nost=%"PRIu64"",
1290 if (nost == num_osts)
1293 llapi_layout_free(layout);
1296 layout = llapi_layout_alloc();
1297 ASSERTF(layout != NULL, "errno %d", errno);
1298 for (i = LOV_MAX_STRIPE_COUNT-1; i >= 0; i--) {
1299 rc = llapi_layout_ost_index_set(layout, i, nost);
1300 ASSERTF(rc == 0, "errno = %d", errno);
1301 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1302 ASSERTF(rc == 0, "errno = %d", errno);
1304 if (nost == num_osts)
1309 for (i = LOV_MAX_STRIPE_COUNT-1; i <= 0; i--) {
1310 rc = llapi_layout_ost_index_get(layout, i, &ost0);
1311 ASSERTF(rc == 0, "errno = %d", errno);
1312 ASSERTF(ost0 == nost, "ost=%"PRIu64", nost=%"PRIu64"",
1315 if (nost == num_osts)
1318 llapi_layout_free(layout);
1321 #define T30FILE "f30"
1322 #define T30_DESC "create composite file, traverse components"
1326 uint64_t start[3], end[3];
1328 struct llapi_layout *layout;
1329 char path[PATH_MAX];
1332 end[0] = 64 * 1024 * 1024; /* 64m */
1334 end[1] = 1 * 1024 * 1024 * 1024; /* 1G */
1336 end[2] = LUSTRE_EOF;
1341 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T30FILE);
1344 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1346 layout = llapi_layout_alloc();
1347 ASSERTF(layout != NULL, "errno %d", errno);
1349 rc = llapi_layout_stripe_count_set(layout, 1);
1350 ASSERTF(rc == 0, "errno %d", errno);
1352 /* add component without adjusting previous component's extent
1354 rc = llapi_layout_comp_add(layout);
1355 ASSERTF(rc == -1 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1357 rc = llapi_layout_comp_extent_set(layout, start[0], end[0]);
1358 ASSERTF(rc == 0, "errno %d", errno);
1360 rc = llapi_layout_comp_add(layout);
1361 ASSERTF(rc == 0, "errno %d", errno);
1363 /* set non-contiguous extent will fail */
1364 rc = llapi_layout_comp_extent_set(layout, end[0] * 2, end[1]);
1365 ASSERTF(rc == -1 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1367 rc = llapi_layout_comp_extent_set(layout, start[1], end[1]);
1368 ASSERTF(rc == 0, "errno %d", errno);
1370 rc = llapi_layout_comp_add(layout);
1371 ASSERTF(rc == 0, "errno %d", errno);
1373 rc = llapi_layout_comp_extent_set(layout, start[2], end[2]);
1374 ASSERTF(rc == 0, "errno %d", errno);
1376 /* create composite file */
1377 fd = llapi_layout_file_create(path, 0, 0660, layout);
1378 ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1380 llapi_layout_free(layout);
1382 /* traverse & verify all components */
1383 layout = llapi_layout_get_by_path(path, 0);
1384 ASSERTF(layout != NULL, "errno = %d", errno);
1386 /* current component should be the tail component */
1387 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1388 ASSERTF(rc == 0, "errno %d", errno);
1389 ASSERTF(s == start[2] && e == end[2],
1390 "s: %"PRIu64", e: %"PRIu64"", s, e);
1392 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1393 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1395 /* delete non-tail component will fail */
1396 rc = llapi_layout_comp_del(layout);
1397 ASSERTF(rc == -1 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1399 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1400 ASSERTF(rc == 0, "errno %d", errno);
1401 ASSERTF(s == start[0] && e == end[0],
1402 "s: %"PRIu64", e: %"PRIu64"", s, e);
1404 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
1405 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1407 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1408 ASSERTF(rc == 0, "errno %d", errno);
1409 ASSERTF(s == start[1] && e == end[1],
1410 "s: %"PRIu64", e: %"PRIu64"", s, e);
1412 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
1413 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1415 rc = llapi_layout_comp_del(layout);
1416 ASSERTF(rc == 0, "errno %d", errno);
1418 llapi_layout_free(layout);
1421 #define T31FILE "f31"
1422 #define T31_DESC "add/delete component to/from existing file"
1426 uint64_t start[2], end[2];
1429 struct llapi_layout *layout;
1430 char path[PATH_MAX];
1433 end[0] = 64 * 1024 * 1024; /* 64m */
1435 end[1] = LUSTRE_EOF;
1440 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T31FILE);
1443 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1445 layout = llapi_layout_alloc();
1446 ASSERTF(layout != NULL, "errno %d", errno);
1448 rc = llapi_layout_stripe_count_set(layout, 1);
1449 ASSERTF(rc == 0, "errno %d", errno);
1451 rc = llapi_layout_comp_extent_set(layout, start[0], end[0]);
1452 ASSERTF(rc == 0, "errno %d", errno);
1454 /* create composite file */
1455 fd = llapi_layout_file_create(path, 0, 0660, layout);
1456 ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno);
1457 llapi_layout_free(layout);
1459 layout = llapi_layout_alloc();
1460 ASSERTF(layout != NULL, "errno %d", errno);
1462 rc = llapi_layout_stripe_count_set(layout, 2);
1463 ASSERTF(rc == 0, "errno %d", errno);
1465 rc = llapi_layout_comp_extent_set(layout, start[1], end[1]);
1466 ASSERTF(rc == 0, "errno %d", errno);
1468 /* add comopnent to existing file */
1469 rc = llapi_layout_file_comp_add(path, layout);
1470 ASSERTF(rc == 0, "errno %d", errno);
1471 llapi_layout_free(layout);
1473 /* verify the composite layout after adding */
1474 layout = llapi_layout_get_by_path(path, 0);
1475 ASSERTF(layout != NULL, "errno = %d", errno);
1477 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1478 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1481 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1482 ASSERTF(rc == 0 && i < 2, "i %d, errno %d", i, errno);
1483 ASSERTF(s == start[i] && e == end[i],
1484 "i: %d s: %"PRIu64", e: %"PRIu64"", i, s, e);
1486 rc = llapi_layout_comp_id_get(layout, &id[i]);
1487 ASSERTF(rc == 0 && id[i] != 0, "i %d, errno %d, id %d",
1490 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
1491 ASSERTF(rc == 0 || i == 1, "i=%d rc=%d errno=%d", i, rc, errno);
1495 /* Verify reverse iteration gives the same IDs as forward iteration */
1496 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_LAST);
1497 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1502 rc = llapi_layout_comp_id_get(layout, &comp_id);
1503 ASSERTF(rc == 0 && comp_id == id[i],
1504 "i %d, errno %d, id[] %u/%u", i, errno, id[i], comp_id);
1506 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_PREV);
1507 ASSERTF(rc == 0 || i == 0, "i=%d rc=%d errno=%d", i, rc, errno);
1510 llapi_layout_free(layout);
1512 /* delete non-tail component will fail */
1513 rc = llapi_layout_file_comp_del(path, id[0], 0);
1514 ASSERTF(rc < 0 && errno == EINVAL, "rc %d, errno %d", rc, errno);
1516 rc = llapi_layout_file_comp_del(path, id[1], 0);
1517 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1519 /* verify the composite layout after deleting */
1520 layout = llapi_layout_get_by_path(path, 0);
1521 ASSERTF(layout != NULL, "errno = %d", errno);
1523 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
1524 ASSERTF(rc == 0, "rc %d, errno %d", rc, errno);
1526 rc = llapi_layout_comp_extent_get(layout, &s, &e);
1527 ASSERTF(rc == 0, "errno %d", errno);
1528 ASSERTF(s == start[0] && e == end[0],
1529 "s: %"PRIu64", e: %"PRIu64"", s, e);
1532 #define TEST_DESC_LEN 50
1533 struct test_tbl_entry {
1534 void (*tte_fn)(void);
1535 char tte_desc[TEST_DESC_LEN];
1539 static struct test_tbl_entry test_tbl[] = {
1540 { .tte_fn = &test0, .tte_desc = T0_DESC, .tte_skip = false },
1541 { .tte_fn = &test1, .tte_desc = T1_DESC, .tte_skip = false },
1542 { .tte_fn = &test2, .tte_desc = T2_DESC, .tte_skip = false },
1543 { .tte_fn = &test3, .tte_desc = T3_DESC, .tte_skip = false },
1544 { .tte_fn = &test4, .tte_desc = T4_DESC, .tte_skip = false },
1545 { .tte_fn = &test5, .tte_desc = T5_DESC, .tte_skip = false },
1546 { .tte_fn = &test6, .tte_desc = T6_DESC, .tte_skip = false },
1547 { .tte_fn = &test7, .tte_desc = T7_DESC, .tte_skip = false },
1548 { .tte_fn = &test8, .tte_desc = T8_DESC, .tte_skip = false },
1549 { .tte_fn = &test9, .tte_desc = T9_DESC, .tte_skip = false },
1550 { .tte_fn = &test10, .tte_desc = T10_DESC, .tte_skip = false },
1551 { .tte_fn = &test11, .tte_desc = T11_DESC, .tte_skip = false },
1552 { .tte_fn = &test12, .tte_desc = T12_DESC, .tte_skip = false },
1553 { .tte_fn = &test13, .tte_desc = T13_DESC, .tte_skip = false },
1554 { .tte_fn = &test14, .tte_desc = T14_DESC, .tte_skip = false },
1555 { .tte_fn = &test15, .tte_desc = T15_DESC, .tte_skip = false },
1556 { .tte_fn = &test16, .tte_desc = T16_DESC, .tte_skip = false },
1557 { .tte_fn = &test17, .tte_desc = T17_DESC, .tte_skip = false },
1558 { .tte_fn = &test18, .tte_desc = T18_DESC, .tte_skip = false },
1559 { .tte_fn = &test19, .tte_desc = T19_DESC, .tte_skip = false },
1560 { .tte_fn = &test20, .tte_desc = T20_DESC, .tte_skip = false },
1561 { .tte_fn = &test21, .tte_desc = T21_DESC, .tte_skip = false },
1562 { .tte_fn = &test22, .tte_desc = T22_DESC, .tte_skip = false },
1563 { .tte_fn = &test23, .tte_desc = T23_DESC, .tte_skip = false },
1564 { .tte_fn = &test24, .tte_desc = T24_DESC, .tte_skip = false },
1565 { .tte_fn = &test25, .tte_desc = T25_DESC, .tte_skip = false },
1566 { .tte_fn = &test26, .tte_desc = T26_DESC, .tte_skip = false },
1567 { .tte_fn = &test27, .tte_desc = T27_DESC, .tte_skip = false },
1568 { .tte_fn = &test28, .tte_desc = T28_DESC, .tte_skip = false },
1569 { .tte_fn = &test29, .tte_desc = T29_DESC, .tte_skip = false },
1570 { .tte_fn = &test30, .tte_desc = T30_DESC, .tte_skip = false },
1571 { .tte_fn = &test31, .tte_desc = T31_DESC, .tte_skip = false },
1574 #define NUM_TESTS (sizeof(test_tbl) / sizeof(struct test_tbl_entry))
1576 void print_test_desc(int test_num, const char *test_desc, const char *status)
1580 printf(" test %2d: %s ", test_num, test_desc);
1581 for (i = 0; i < TEST_DESC_LEN - strlen(test_desc); i++)
1583 printf(" %s\n", status);
1586 /* This function runs a single test by forking the process. This way,
1587 * if there is a segfault during a test, the test program won't crash. */
1588 int test(void (*test_fn)(), const char *test_desc, bool test_skip, int test_num)
1592 char status_buf[128];
1595 print_test_desc(test_num, test_desc, "skip");
1601 ERROR("cannot fork: %s", strerror(errno));
1602 } else if (pid > 0) {
1605 /* Non-zero value indicates failure. */
1608 strncpy(status_buf, "pass", sizeof(status_buf));
1609 } else if WIFSIGNALED(status) {
1610 snprintf(status_buf, sizeof(status_buf),
1611 "fail (exit status %d, killed by SIG%d)",
1612 WEXITSTATUS(status), WTERMSIG(status));
1615 snprintf(status_buf, sizeof(status_buf),
1616 "fail (exit status %d)", WEXITSTATUS(status));
1619 print_test_desc(test_num, test_desc, status_buf);
1620 } else if (pid == 0) {
1621 /* Run the test in the child process. Exit with 0 for success,
1622 * non-zero for failure */
1630 /* 'str_tests' are the tests to be skipped, such as "1,3,4,.." */
1631 static void set_tests_skipped(char *str_tests)
1633 char *ptr = str_tests;
1636 if (ptr == NULL || strlen(ptr) == 0)
1639 while (*ptr != '\0') {
1640 tstno = strtoul(ptr, &ptr, 0);
1641 if (tstno >= 0 && tstno < NUM_TESTS)
1642 test_tbl[tstno].tte_skip = true;
1650 static void process_args(int argc, char *argv[])
1654 while ((c = getopt(argc, argv, "d:p:o:s:")) != -1) {
1657 lustre_dir = optarg;
1663 num_osts = atoi(optarg);
1666 set_tests_skipped(optarg);
1669 fprintf(stderr, "Unknown option '%c'\n", optopt);
1675 int main(int argc, char *argv[])
1682 llapi_msg_set_level(LLAPI_MSG_OFF);
1684 process_args(argc, argv);
1685 if (lustre_dir == NULL)
1686 lustre_dir = "/mnt/lustre";
1687 if (poolname == NULL)
1688 poolname = "testpool";
1693 DIE("Error: at least 2 OSTS are required\n");
1695 if (stat(lustre_dir, &s) < 0)
1696 DIE("cannot stat %s: %s\n", lustre_dir, strerror(errno));
1697 else if (!S_ISDIR(s.st_mode))
1698 DIE("%s: not a directory\n", lustre_dir);
1700 rc = llapi_search_fsname(lustre_dir, fsname);
1702 fprintf(stderr, "Error: %s: not a Lustre filesystem\n",
1707 /* Play nice with Lustre test scripts. Non-line buffered output
1708 * stream under I/O redirection may appear incorrectly. */
1709 setvbuf(stdout, NULL, _IOLBF, 0);
1711 for (i = 0; i < NUM_TESTS; i++) {
1712 struct test_tbl_entry *tst = &test_tbl[i];
1713 if (test(tst->tte_fn, tst->tte_desc, tst->tte_skip, i) != 0)