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]\n",
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);
177 #define T2_DESC "Read test0 file by FD and verify attributes"
184 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
186 fd = open(path, O_RDONLY);
187 ASSERTF(fd >= 0, "open(%s): errno = %d", path, errno);
189 struct llapi_layout *layout = llapi_layout_get_by_fd(fd, 0);
190 ASSERTF(layout != NULL, "errno = %d", errno);
193 ASSERTF(rc == 0, "close(%s): errno = %d", path, errno);
195 __test1_helper(layout);
196 llapi_layout_free(layout);
199 #define T3_DESC "Read test0 file by FID and verify attributes"
203 struct llapi_layout *layout;
208 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
210 rc = llapi_path2fid(path, &fid);
211 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
212 snprintf(fidstr, sizeof(fidstr), "0x%"PRIx64":0x%x:0x%x",
213 (uint64_t)fid.f_seq, fid.f_oid, fid.f_ver);
215 layout = llapi_layout_get_by_fid(path, &fid, 0);
216 ASSERTF(layout != NULL, "fidstr = %s, errno = %d", fidstr, errno);
218 __test1_helper(layout);
219 llapi_layout_free(layout);
224 #define T4_STRIPE_COUNT 2
225 #define T4_STRIPE_SIZE 2097152
226 #define T4_DESC "Verify compatibility with 'lfs setstripe'"
234 const char *lfs = getenv("LFS");
235 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
239 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T4FILE);
242 lfs = "/usr/bin/lfs";
245 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
247 snprintf(cmd, sizeof(cmd), "%s setstripe %s %s -c %d -s %d %s", lfs,
248 strlen(poolname) > 0 ? "-p" : "", poolname, T4_STRIPE_COUNT,
249 T4_STRIPE_SIZE, path);
251 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
254 struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
255 ASSERTF(layout != NULL, "errno = %d", errno);
257 rc = llapi_layout_stripe_count_get(layout, &count);
258 ASSERTF(count == T4_STRIPE_COUNT, "%"PRIu64" != %d", count,
261 rc = llapi_layout_stripe_size_get(layout, &size);
262 ASSERTF(size == T4_STRIPE_SIZE, "%"PRIu64" != %d", size,
265 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
266 ASSERTF(rc == 0, "errno = %d", errno);
267 rc = strcmp(mypool, poolname);
268 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
270 rc = llapi_layout_ost_index_get(layout, 0, &ost0);
271 ASSERTF(rc == 0, "errno = %d", errno);
272 rc = llapi_layout_ost_index_get(layout, 1, &ost1);
273 ASSERTF(rc == 0, "errno = %d", errno);
274 ASSERTF(ost1 != ost0, "%"PRIu64" == %"PRIu64, ost0, ost1);
276 llapi_layout_free(layout);
280 #define T5_DESC "llapi_layout_get_by_path ENOENT handling"
285 struct llapi_layout *layout;
287 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T5FILE);
290 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
293 layout = llapi_layout_get_by_path(path, 0);
294 ASSERTF(layout == NULL && errno == ENOENT, "errno = %d", errno);
297 #define T6_DESC "llapi_layout_get_by_fd EBADF handling"
301 struct llapi_layout *layout = llapi_layout_get_by_fd(9999, 0);
302 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);
349 /* llapi_layout_get_by_path() returns default layout for file with no
350 * striping attributes. */
352 #define T8_DESC "llapi_layout_get_by_path ENODATA handling"
357 struct llapi_layout *layout;
363 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T8FILE);
366 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
367 fd = open(path, O_CREAT, 0640);
368 ASSERTF(fd >= 0, "errno = %d", errno);
370 ASSERTF(rc == 0, "errno = %d", errno);
372 layout = llapi_layout_get_by_path(path, 0);
373 ASSERTF(layout != NULL, "errno = %d\n", errno);
375 rc = llapi_layout_stripe_count_get(layout, &count);
376 ASSERTF(rc == 0, "errno = %d\n", errno);
377 ASSERTF(count == LLAPI_LAYOUT_DEFAULT, "count = %"PRIu64"\n", count);
379 rc = llapi_layout_stripe_size_get(layout, &size);
380 ASSERTF(rc == 0, "errno = %d\n", errno);
381 ASSERTF(size == LLAPI_LAYOUT_DEFAULT, "size = %"PRIu64"\n", size);
383 rc = llapi_layout_pattern_get(layout, &pattern);
384 ASSERTF(rc == 0, "errno = %d\n", errno);
385 ASSERTF(pattern == LLAPI_LAYOUT_DEFAULT, "pattern = %"PRIu64"\n",
388 llapi_layout_free(layout);
391 /* Setting pattern > 0 returns EOPNOTSUPP in errno. */
392 #define T9_DESC "llapi_layout_pattern_set() EOPNOTSUPP handling"
395 struct llapi_layout *layout;
398 layout = llapi_layout_alloc();
399 ASSERTF(layout != NULL, "errno = %d\n", errno);
401 rc = llapi_layout_pattern_set(layout, 1);
402 ASSERTF(rc == -1 && errno == EOPNOTSUPP, "rc = %d, errno = %d", rc,
404 llapi_layout_free(layout);
408 /* Verify stripe_count interfaces return errors as expected */
409 #define T10_DESC "stripe_count error handling"
414 struct llapi_layout *layout;
416 layout = llapi_layout_alloc();
417 ASSERTF(layout != NULL, "errno = %d", errno);
419 /* invalid stripe count */
421 rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_INVALID);
422 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
425 rc = llapi_layout_stripe_count_set(layout, -1);
426 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
430 rc = llapi_layout_stripe_count_set(NULL, 2);
431 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
435 rc = llapi_layout_stripe_count_get(NULL, &count);
436 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
440 rc = llapi_layout_stripe_count_get(layout, NULL);
441 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
443 /* stripe count too large */
445 rc = llapi_layout_stripe_count_set(layout, LOV_MAX_STRIPE_COUNT + 1);
446 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
447 llapi_layout_free(layout);
450 /* Verify stripe_size interfaces return errors as expected */
451 #define T11_DESC "stripe_size error handling"
456 struct llapi_layout *layout;
458 layout = llapi_layout_alloc();
459 ASSERTF(layout != NULL, "errno = %d", errno);
461 /* negative stripe size */
463 rc = llapi_layout_stripe_size_set(layout, -1);
464 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
466 /* invalid stripe size */
468 rc = llapi_layout_stripe_size_set(layout, LLAPI_LAYOUT_INVALID);
469 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
471 /* stripe size too big */
473 rc = llapi_layout_stripe_size_set(layout, (1ULL << 33));
474 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
478 rc = llapi_layout_stripe_size_set(NULL, 1048576);
479 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
482 rc = llapi_layout_stripe_size_get(NULL, &size);
483 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
487 rc = llapi_layout_stripe_size_get(layout, NULL);
488 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
490 llapi_layout_free(layout);
493 /* Verify pool_name interfaces return errors as expected */
494 #define T12_DESC "pool_name error handling"
498 struct llapi_layout *layout;
499 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
501 layout = llapi_layout_alloc();
502 ASSERTF(layout != NULL, "errno = %d", errno);
506 rc = llapi_layout_pool_name_set(NULL, "foo");
507 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
511 rc = llapi_layout_pool_name_set(layout, NULL);
512 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
516 rc = llapi_layout_pool_name_get(NULL, mypool, sizeof(mypool));
517 ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
521 rc = llapi_layout_pool_name_get(layout, NULL, sizeof(mypool));
522 ASSERTF(errno == EINVAL, "poolname = %s, errno = %d", poolname, errno);
524 /* Pool name too long*/
526 rc = llapi_layout_pool_name_set(layout, "0123456789abcdef");
527 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
529 llapi_layout_free(layout);
532 /* Verify ost_index interface returns errors as expected */
533 #define T13FILE "t13"
534 #define T13_STRIPE_COUNT 2
535 #define T13_DESC "ost_index error handling"
541 struct llapi_layout *layout;
544 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T13FILE);
546 layout = llapi_layout_alloc();
547 ASSERTF(layout != NULL, "errno = %d", errno);
549 /* Only setting OST index for stripe 0 is supported for now. */
551 rc = llapi_layout_ost_index_set(layout, 1, 1);
552 ASSERTF(rc == -1 && errno == EOPNOTSUPP, "rc = %d, errno = %d",
555 /* invalid OST index */
557 rc = llapi_layout_ost_index_set(layout, 0, LLAPI_LAYOUT_INVALID);
558 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
561 rc = llapi_layout_ost_index_set(layout, 0, -1);
562 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
566 rc = llapi_layout_ost_index_set(NULL, 0, 1);
567 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
570 rc = llapi_layout_ost_index_get(NULL, 0, &idx);
571 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
575 rc = llapi_layout_ost_index_get(layout, 0, NULL);
576 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
578 /* Layout not read from file so has no OST data. */
580 rc = llapi_layout_stripe_count_set(layout, T13_STRIPE_COUNT);
581 ASSERTF(rc == 0, "errno = %d", errno);
582 rc = llapi_layout_ost_index_get(layout, 0, &idx);
583 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
585 /* n greater than stripe count*/
587 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
588 rc = llapi_layout_stripe_count_set(layout, T13_STRIPE_COUNT);
589 ASSERTF(rc == 0, "errno = %d", errno);
590 fd = llapi_layout_file_create(path, 0, 0644, layout);
591 ASSERTF(fd >= 0, "errno = %d", errno);
593 ASSERTF(rc == 0, "errno = %d", errno);
594 llapi_layout_free(layout);
596 layout = llapi_layout_get_by_path(path, 0);
597 ASSERTF(layout != NULL, "errno = %d", errno);
599 rc = llapi_layout_ost_index_get(layout, T13_STRIPE_COUNT + 1, &idx);
600 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
602 llapi_layout_free(layout);
605 /* Verify llapi_layout_file_create() returns errors as expected */
606 #define T14_DESC "llapi_layout_file_create error handling"
610 struct llapi_layout *layout = llapi_layout_alloc();
614 rc = llapi_layout_file_create(NULL, 0, 0, layout);
615 ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d", rc, errno);
617 llapi_layout_free(layout);
620 /* Can't change striping attributes of existing file. */
621 #define T15FILE "t15"
622 #define T15_STRIPE_COUNT 2
623 #define T15_DESC "Can't change striping attributes of existing file"
629 struct llapi_layout *layout;
632 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T15FILE);
635 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
637 layout = llapi_layout_alloc();
638 ASSERTF(layout != NULL, "errno = %d", errno);
639 rc = llapi_layout_stripe_count_set(layout, T15_STRIPE_COUNT);
640 ASSERTF(rc == 0, "errno = %d", errno);
643 fd = llapi_layout_file_create(path, 0, 0640, layout);
644 ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
646 ASSERTF(rc == 0, "errno = %d", errno);
648 rc = llapi_layout_stripe_count_set(layout, T15_STRIPE_COUNT - 1);
650 fd = llapi_layout_file_open(path, 0, 0640, layout);
651 ASSERTF(fd >= 0, "fd = %d, errno = %d", fd, errno);
653 ASSERTF(rc == 0, "errno = %d", errno);
654 llapi_layout_free(layout);
656 layout = llapi_layout_get_by_path(path, 0);
657 ASSERTF(layout != NULL, "errno = %d", errno);
658 rc = llapi_layout_stripe_count_get(layout, &count);
659 ASSERTF(rc == 0 && count == T15_STRIPE_COUNT,
660 "rc = %d, %"PRIu64" != %d", rc, count, T15_STRIPE_COUNT);
661 llapi_layout_free(layout);
664 /* Default stripe attributes are applied as expected. */
665 #define T16FILE "t16"
666 #define T16_DESC "Default stripe attributes are applied as expected"
671 struct llapi_layout *deflayout;
672 struct llapi_layout *filelayout;
679 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T16FILE);
682 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
684 deflayout = llapi_layout_get_by_path(lustre_dir, LAYOUT_GET_EXPECTED);
685 ASSERTF(deflayout != NULL, "errno = %d", errno);
686 rc = llapi_layout_stripe_size_get(deflayout, &dsize);
687 ASSERTF(rc == 0, "errno = %d", errno);
688 rc = llapi_layout_stripe_count_get(deflayout, &dcount);
689 ASSERTF(rc == 0, "errno = %d", errno);
691 /* First, with a default struct llapi_layout */
692 filelayout = llapi_layout_alloc();
693 ASSERTF(filelayout != NULL, "errno = %d", errno);
695 fd = llapi_layout_file_create(path, 0, 0640, filelayout);
696 ASSERTF(fd >= 0, "errno = %d", errno);
699 ASSERTF(rc == 0, "errno = %d", errno);
701 llapi_layout_free(filelayout);
703 filelayout = llapi_layout_get_by_path(path, 0);
704 ASSERTF(filelayout != NULL, "errno = %d", errno);
706 rc = llapi_layout_stripe_count_get(filelayout, &fcount);
707 ASSERTF(rc == 0, "errno = %d", errno);
708 ASSERTF(fcount == dcount, "%"PRIu64" != %"PRIu64, fcount, dcount);
710 rc = llapi_layout_stripe_size_get(filelayout, &fsize);
711 ASSERTF(rc == 0, "errno = %d", errno);
712 ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
714 /* NULL layout also implies default layout */
716 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
718 fd = llapi_layout_file_create(path, 0, 0640, filelayout);
719 ASSERTF(fd >= 0, "errno = %d", errno);
721 ASSERTF(rc == 0, "errno = %d", errno);
722 filelayout = llapi_layout_get_by_path(path, 0);
723 ASSERTF(filelayout != NULL, "errno = %d", errno);
725 rc = llapi_layout_stripe_count_get(filelayout, &fcount);
726 ASSERTF(rc == 0, "errno = %d", errno);
727 rc = llapi_layout_stripe_size_get(filelayout, &fsize);
728 ASSERTF(rc == 0, "errno = %d", errno);
729 ASSERTF(fcount == dcount, "%"PRIu64" != %"PRIu64, fcount, dcount);
730 ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
732 llapi_layout_free(filelayout);
733 llapi_layout_free(deflayout);
736 /* Setting stripe count to LLAPI_LAYOUT_WIDE uses all available OSTs. */
737 #define T17FILE "t17"
738 #define T17_DESC "LLAPI_LAYOUT_WIDE is honored"
744 uint64_t osts_layout;
745 struct llapi_layout *layout;
748 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T17FILE);
751 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
752 layout = llapi_layout_alloc();
753 ASSERTF(layout != NULL, "errno = %d", errno);
754 rc = llapi_layout_stripe_count_set(layout, LLAPI_LAYOUT_WIDE);
755 ASSERTF(rc == 0, "errno = %d", errno);
756 fd = llapi_layout_file_create(path, 0, 0640, layout);
757 ASSERTF(fd >= 0, "errno = %d", errno);
759 ASSERTF(rc == 0, "errno = %d", errno);
760 llapi_layout_free(layout);
762 /* Get number of available OSTs */
763 fd = open(path, O_RDONLY);
764 ASSERTF(fd >= 0, "errno = %d", errno);
765 rc = llapi_lov_get_uuids(fd, NULL, &osts_all);
766 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
768 ASSERTF(rc == 0, "errno = %d", errno);
770 layout = llapi_layout_get_by_path(path, 0);
771 ASSERTF(layout != NULL, "errno = %d", errno);
772 rc = llapi_layout_stripe_count_get(layout, &osts_layout);
773 ASSERTF(osts_layout == osts_all, "%"PRIu64" != %d", osts_layout,
776 llapi_layout_free(layout);
779 /* Setting pool with "fsname.pool" notation. */
780 #define T18FILE "t18"
781 #define T18_DESC "Setting pool with fsname.pool notation"
786 struct llapi_layout *layout = llapi_layout_alloc();
788 char pool[LOV_MAXPOOLNAME*2 + 1];
789 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
791 snprintf(pool, sizeof(pool), "lustre.%s", poolname);
793 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T18FILE);
795 ASSERTF(layout != NULL, "errno = %d", errno);
798 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
800 rc = llapi_layout_pool_name_set(layout, pool);
801 ASSERTF(rc == 0, "errno = %d", errno);
803 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
804 ASSERTF(rc == 0, "errno = %d", errno);
805 rc = strcmp(mypool, poolname);
806 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
807 fd = llapi_layout_file_create(path, 0, 0640, layout);
808 ASSERTF(fd >= 0, "errno = %d", errno);
810 ASSERTF(rc == 0, "errno = %d", errno);
812 llapi_layout_free(layout);
814 layout = llapi_layout_get_by_path(path, 0);
815 ASSERTF(layout != NULL, "errno = %d", errno);
816 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
817 ASSERTF(rc == 0, "errno = %d", errno);
818 rc = strcmp(mypool, poolname);
819 ASSERTF(rc == 0, "%s != %s", mypool, poolname);
820 llapi_layout_free(layout);
823 #define T19_DESC "Maximum length pool name is NULL-terminated"
826 struct llapi_layout *layout;
827 char *name = "0123456789abcde";
828 char mypool[LOV_MAXPOOLNAME + 1] = { '\0' };
831 layout = llapi_layout_alloc();
832 ASSERTF(layout != NULL, "errno = %d", errno);
833 rc = llapi_layout_pool_name_set(layout, name);
834 ASSERTF(rc == 0, "errno = %d", errno);
835 rc = llapi_layout_pool_name_get(layout, mypool, sizeof(mypool));
836 ASSERTF(strlen(name) == strlen(mypool), "name = %s, str = %s", name,
838 llapi_layout_free(layout);
841 #define T20FILE "t20"
842 #define T20_DESC "LLAPI_LAYOUT_DEFAULT is honored"
847 struct llapi_layout *deflayout;
848 struct llapi_layout *filelayout;
855 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T20FILE);
858 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
860 filelayout = llapi_layout_alloc();
861 ASSERTF(filelayout != NULL, "errno = %d", errno);
863 rc = llapi_layout_stripe_size_set(filelayout, LLAPI_LAYOUT_DEFAULT);
864 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
866 rc = llapi_layout_stripe_count_set(filelayout, LLAPI_LAYOUT_DEFAULT);
867 ASSERTF(rc == 0, "rc = %d, errno = %d", rc, errno);
869 fd = llapi_layout_file_create(path, 0, 0640, filelayout);
870 ASSERTF(fd >= 0, "errno = %d", errno);
873 ASSERTF(rc == 0, "errno = %d", errno);
875 llapi_layout_free(filelayout);
877 deflayout = llapi_layout_get_by_path(lustre_dir, LAYOUT_GET_EXPECTED);
878 ASSERTF(deflayout != NULL, "errno = %d", errno);
880 filelayout = llapi_layout_get_by_path(path, 0);
881 ASSERTF(filelayout != NULL, "errno = %d", errno);
883 rc = llapi_layout_stripe_count_get(filelayout, &fcount);
884 ASSERTF(rc == 0, "errno = %d", errno);
885 rc = llapi_layout_stripe_count_get(deflayout, &dcount);
886 ASSERTF(rc == 0, "errno = %d", errno);
887 ASSERTF(fcount == dcount, "%"PRIu64" != %"PRIu64, fcount, dcount);
889 rc = llapi_layout_stripe_size_get(filelayout, &fsize);
890 ASSERTF(rc == 0, "errno = %d", errno);
891 rc = llapi_layout_stripe_size_get(deflayout, &dsize);
892 ASSERTF(rc == 0, "errno = %d", errno);
893 ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
895 llapi_layout_free(filelayout);
896 llapi_layout_free(deflayout);
899 #define T21_DESC "llapi_layout_file_create fails for non-Lustre file"
902 struct llapi_layout *layout;
903 char template[PATH_MAX];
907 snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
908 fd = mkstemp(template);
909 ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
911 ASSERTF(rc == 0, "errno = %d", fd);
912 rc = unlink(template);
913 ASSERTF(rc == 0, "errno = %d", errno);
915 layout = llapi_layout_alloc();
916 ASSERTF(layout != NULL, "errno = %d", errno);
918 fd = llapi_layout_file_create(template, 0, 0640, layout);
919 ASSERTF(fd == -1 && errno == ENOTTY,
920 "fd = %d, errno = %d, template = %s", fd, errno, template);
921 llapi_layout_free(layout);
924 #define T22FILE "t22"
925 #define T22_DESC "llapi_layout_file_create applied mode correctly"
932 mode_t mode_in = 0640;
936 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T22FILE);
939 ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
941 umask_orig = umask(S_IWGRP | S_IWOTH);
943 fd = llapi_layout_file_create(path, 0, mode_in, NULL);
944 ASSERTF(fd >= 0, "errno = %d", errno);
946 (void) umask(umask_orig);
949 ASSERTF(rc == 0, "errno = %d", errno);
952 ASSERTF(rc == 0, "errno = %d", fd);
954 mode_out = st.st_mode & ~S_IFMT;
955 ASSERTF(mode_in == mode_out, "%o != %o", mode_in, mode_out);
958 #define T23_DESC "llapi_layout_get_by_path fails for non-Lustre file"
961 struct llapi_layout *layout;
962 char template[PATH_MAX];
966 snprintf(template, sizeof(template), "%s/XXXXXX", P_tmpdir);
967 fd = mkstemp(template);
968 ASSERTF(fd >= 0, "template = %s, errno = %d", template, errno);
970 ASSERTF(rc == 0, "errno = %d", fd);
972 layout = llapi_layout_get_by_path(template, 0);
973 ASSERTF(layout == NULL && errno == ENOTTY,
974 "errno = %d, template = %s", errno, template);
976 rc = unlink(template);
977 ASSERTF(rc == 0, "errno = %d", errno);
980 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
981 * for file with unspecified layout. */
982 #define T24FILE "t24"
983 #define T24_DESC "LAYOUT_GET_EXPECTED works with existing file"
988 struct llapi_layout *layout;
994 snprintf(path, sizeof(path), "%s/%s", lustre_dir, T24FILE);
997 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
998 fd = open(path, O_CREAT, 0640);
999 ASSERTF(fd >= 0, "errno = %d", errno);
1001 ASSERTF(rc == 0, "errno = %d", errno);
1003 layout = llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED);
1004 ASSERTF(layout != NULL, "errno = %d\n", errno);
1006 rc = llapi_layout_stripe_count_get(layout, &count);
1007 ASSERTF(rc == 0, "errno = %d\n", errno);
1008 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1010 rc = llapi_layout_stripe_size_get(layout, &size);
1011 ASSERTF(rc == 0, "errno = %d\n", errno);
1012 ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1014 rc = llapi_layout_pattern_get(layout, &pattern);
1015 ASSERTF(rc == 0, "errno = %d\n", errno);
1016 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1018 llapi_layout_free(layout);
1021 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
1022 * for directory with unspecified layout. */
1023 #define T25DIR "d25"
1024 #define T25_DESC "LAYOUT_GET_EXPECTED works with directory"
1028 struct llapi_layout *layout;
1034 snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T25DIR);
1037 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1038 rc = mkdir(dir, 0750);
1039 ASSERTF(rc == 0, "errno = %d", errno);
1041 layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1042 ASSERTF(layout != NULL, "errno = %d\n", errno);
1044 rc = llapi_layout_stripe_count_get(layout, &count);
1045 ASSERTF(rc == 0, "errno = %d\n", errno);
1046 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1048 rc = llapi_layout_stripe_size_get(layout, &size);
1049 ASSERTF(rc == 0, "errno = %d\n", errno);
1050 ASSERTF(size != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1052 rc = llapi_layout_pattern_get(layout, &pattern);
1053 ASSERTF(rc == 0, "errno = %d\n", errno);
1054 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1056 llapi_layout_free(layout);
1059 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) correctly combines
1060 * specified attributes of parent directory with attributes filesystem root. */
1061 #define T26DIR "d26"
1062 #define T26_DESC "LAYOUT_GET_EXPECTED partially specified parent"
1063 #define T26_STRIPE_SIZE (1048576 * 4)
1067 struct llapi_layout *layout;
1068 const char *lfs = getenv("LFS");
1075 snprintf(dir, sizeof(dir), "%s/%s", lustre_dir, T26DIR);
1077 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1078 rc = mkdir(dir, 0750);
1079 ASSERTF(rc == 0, "errno = %d", errno);
1082 lfs = "/usr/bin/lfs";
1084 snprintf(cmd, sizeof(cmd), "%s setstripe -s %d %s", lfs,
1085 T26_STRIPE_SIZE, dir);
1087 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1089 layout = llapi_layout_get_by_path(dir, LAYOUT_GET_EXPECTED);
1090 ASSERTF(layout != NULL, "errno = %d\n", errno);
1092 rc = llapi_layout_stripe_count_get(layout, &count);
1093 ASSERTF(rc == 0, "errno = %d\n", errno);
1094 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1096 rc = llapi_layout_stripe_size_get(layout, &size);
1097 ASSERTF(rc == 0, "errno = %d\n", errno);
1098 ASSERTF(size == T26_STRIPE_SIZE, "size = %"PRIu64, size);
1100 rc = llapi_layout_pattern_get(layout, &pattern);
1101 ASSERTF(rc == 0, "errno = %d\n", errno);
1102 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1104 llapi_layout_free(layout);
1107 /* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) work with
1108 * non existing file. */
1109 #define T27DIR "d27"
1110 #define T27_DESC "LAYOUT_GET_EXPECTED with non existing file"
1111 #define T27_STRIPE_SIZE (1048576 * 3)
1115 struct llapi_layout *layout;
1116 const char *lfs = getenv("LFS");
1120 char dirpath[PATH_MAX];
1121 char filepath[PATH_MAX];
1124 snprintf(dirpath, sizeof(dirpath), "%s/%s", lustre_dir, T27DIR);
1125 snprintf(filepath, sizeof(filepath), "%s/nonesuch", dirpath);
1127 rc = rmdir(dirpath);
1128 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1129 rc = mkdir(dirpath, 0750);
1130 ASSERTF(rc == 0, "errno = %d", errno);
1133 lfs = "/usr/bin/lfs";
1135 snprintf(cmd, sizeof(cmd), "%s setstripe -s %d %s", lfs,
1136 T27_STRIPE_SIZE, dirpath);
1138 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1140 layout = llapi_layout_get_by_path(filepath, LAYOUT_GET_EXPECTED);
1141 ASSERTF(layout != NULL, "errno = %d\n", errno);
1143 rc = llapi_layout_stripe_count_get(layout, &count);
1144 ASSERTF(rc == 0, "errno = %d\n", errno);
1145 ASSERTF(count != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1147 rc = llapi_layout_stripe_size_get(layout, &size);
1148 ASSERTF(rc == 0, "errno = %d\n", errno);
1149 ASSERTF(size == T27_STRIPE_SIZE, "size = %"PRIu64, size);
1151 rc = llapi_layout_pattern_get(layout, &pattern);
1152 ASSERTF(rc == 0, "errno = %d\n", errno);
1153 ASSERTF(pattern != LLAPI_LAYOUT_DEFAULT, "expected literal value");
1155 llapi_layout_free(layout);
1158 /* llapi_layout_stripe_count_get returns LLAPI_LAYOUT_WIDE for a directory
1159 * with a stripe_count of -1. */
1160 #define T28DIR "d28"
1161 #define T28_DESC "LLAPI_LAYOUT_WIDE returned as expected"
1165 struct llapi_layout *layout;
1166 const char *lfs = getenv("LFS");
1168 char dirpath[PATH_MAX];
1171 snprintf(dirpath, sizeof(dirpath), "%s/%s", lustre_dir, T28DIR);
1173 rc = rmdir(dirpath);
1174 ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno);
1175 rc = mkdir(dirpath, 0750);
1176 ASSERTF(rc == 0, "errno = %d", errno);
1179 lfs = "/usr/bin/lfs";
1181 snprintf(cmd, sizeof(cmd), "%s setstripe -c -1 %s", lfs, dirpath);
1183 ASSERTF(rc == 0, "system(%s): exit status %d", cmd, WEXITSTATUS(rc));
1185 layout = llapi_layout_get_by_path(dirpath, 0);
1186 ASSERTF(layout != NULL, "errno = %d\n", errno);
1188 rc = llapi_layout_stripe_count_get(layout, &count);
1189 ASSERTF(rc == 0, "errno = %d\n", errno);
1190 ASSERTF(count == LLAPI_LAYOUT_WIDE, "count = %"PRIu64"\n", count);
1192 llapi_layout_free(layout);
1195 #define TEST_DESC_LEN 50
1196 struct test_tbl_entry {
1197 void (*tte_fn)(void);
1198 char tte_desc[TEST_DESC_LEN];
1202 static struct test_tbl_entry test_tbl[] = {
1203 { &test0, T0_DESC, false },
1204 { &test1, T1_DESC, false },
1205 { &test2, T2_DESC, false },
1206 { &test3, T3_DESC, false },
1207 { &test4, T4_DESC, false },
1208 { &test5, T5_DESC, false },
1209 { &test6, T6_DESC, false },
1210 { &test7, T7_DESC, false },
1211 { &test8, T8_DESC, false },
1212 { &test9, T9_DESC, false },
1213 { &test10, T10_DESC, false },
1214 { &test11, T11_DESC, false },
1215 { &test12, T12_DESC, false },
1216 { &test13, T13_DESC, false },
1217 { &test14, T14_DESC, false },
1218 { &test15, T15_DESC, false },
1219 { &test16, T16_DESC, false },
1220 { &test17, T17_DESC, false },
1221 { &test18, T18_DESC, false },
1222 { &test19, T19_DESC, false },
1223 { &test20, T20_DESC, false },
1224 { &test21, T21_DESC, false },
1225 { &test22, T22_DESC, false },
1226 { &test23, T23_DESC, false },
1227 { &test24, T24_DESC, false },
1228 { &test25, T25_DESC, false },
1229 { &test26, T26_DESC, false },
1230 { &test27, T27_DESC, false },
1231 { &test28, T28_DESC, false },
1233 #define NUM_TESTS (sizeof(test_tbl) / sizeof(struct test_tbl_entry))
1235 void print_test_desc(int test_num, const char *test_desc, const char *status)
1239 printf(" test %2d: %s ", test_num, test_desc);
1240 for (i = 0; i < TEST_DESC_LEN - strlen(test_desc); i++)
1242 printf(" %s\n", status);
1245 /* This function runs a single test by forking the process. This way,
1246 * if there is a segfault during a test, the test program won't crash. */
1247 int test(void (*test_fn)(), const char *test_desc, bool test_skip, int test_num)
1251 char status_buf[128];
1254 print_test_desc(test_num, test_desc, "skip");
1260 ERROR("cannot fork: %s", strerror(errno));
1261 } else if (pid > 0) {
1264 /* Non-zero value indicates failure. */
1267 strncpy(status_buf, "pass", sizeof(status_buf));
1268 } else if WIFSIGNALED(status) {
1269 snprintf(status_buf, sizeof(status_buf),
1270 "fail (exit status %d, killed by SIG%d)",
1271 WEXITSTATUS(status), WTERMSIG(status));
1274 snprintf(status_buf, sizeof(status_buf),
1275 "fail (exit status %d)", WEXITSTATUS(status));
1278 print_test_desc(test_num, test_desc, status_buf);
1279 } else if (pid == 0) {
1280 /* Run the test in the child process. Exit with 0 for success,
1281 * non-zero for failure */
1289 static void process_args(int argc, char *argv[])
1293 while ((c = getopt(argc, argv, "d:p:o:")) != -1) {
1296 lustre_dir = optarg;
1302 num_osts = atoi(optarg);
1305 fprintf(stderr, "Unknown option '%c'\n", optopt);
1311 int main(int argc, char *argv[])
1318 llapi_msg_set_level(LLAPI_MSG_OFF);
1320 process_args(argc, argv);
1321 if (lustre_dir == NULL)
1322 lustre_dir = "/mnt/lustre";
1323 if (poolname == NULL)
1324 poolname = "testpool";
1329 DIE("Error: at least 2 OSTS are required\n");
1331 if (stat(lustre_dir, &s) < 0)
1332 DIE("cannot stat %s: %s\n", lustre_dir, strerror(errno));
1333 else if (!S_ISDIR(s.st_mode))
1334 DIE("%s: not a directory\n", lustre_dir);
1336 rc = llapi_search_fsname(lustre_dir, fsname);
1338 fprintf(stderr, "Error: %s: not a Lustre filesystem\n",
1343 /* Play nice with Lustre test scripts. Non-line buffered output
1344 * stream under I/O redirection may appear incorrectly. */
1345 setvbuf(stdout, NULL, _IOLBF, 0);
1347 for (i = 0; i < NUM_TESTS; i++) {
1348 struct test_tbl_entry *tst = &test_tbl[i];
1349 if (test(tst->tte_fn, tst->tte_desc, tst->tte_skip, i) != 0)