From: Frank Zago Date: Wed, 15 Oct 2014 19:19:44 +0000 (-0500) Subject: LU-4239 tests: test FID related APIs X-Git-Tag: 2.7.51~42 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=refs%2Fchanges%2F45%2F12545%2F11;p=fs%2Flustre-release.git LU-4239 tests: test FID related APIs This adds a few stress tests to the user lustre API, related to FIDs. Change-Id: I34144a8f4c446e55c6630d31cae6a133d61eb304 Signed-off-by: Frank Zago Test-Parameters: alwaysuploadlogs envdefinitions=ONLY=154g testlist=sanity Reviewed-on: http://review.whamcloud.com/12545 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: John L. Hammond Reviewed-by: Jian Yu Reviewed-by: Oleg Drokin --- diff --git a/lustre/tests/Makefile.am b/lustre/tests/Makefile.am index 4c4cc9f..6afc47a 100644 --- a/lustre/tests/Makefile.am +++ b/lustre/tests/Makefile.am @@ -77,7 +77,7 @@ noinst_PROGRAMS += mmap_sanity writemany reads flocks_test flock_deadlock noinst_PROGRAMS += write_time_limit rwv lgetxattr_size_check checkfiemap noinst_PROGRAMS += listxattr_size_check check_fhandle_syscalls badarea_io noinst_PROGRAMS += llapi_layout_test orphan_linkea_check llapi_hsm_test -noinst_PROGRAMS += group_lock_test +noinst_PROGRAMS += group_lock_test llapi_fid_test bin_PROGRAMS = mcreate munlink testdir = $(libdir)/lustre/tests @@ -94,6 +94,7 @@ multiop_LDADD=$(LIBLUSTREAPI) $(PTHREAD_LIBS) $(LIBCFS) llapi_layout_test_LDADD=$(LIBLUSTREAPI) llapi_hsm_test_LDADD=$(LIBLUSTREAPI) group_lock_test_LDADD=$(LIBLUSTREAPI) +llapi_fid_test_LDADD=$(LIBLUSTREAPI) it_test_LDADD=$(LIBCFS) rwv_LDADD=$(LIBCFS) diff --git a/lustre/tests/llapi_fid_test.c b/lustre/tests/llapi_fid_test.c new file mode 100644 index 0000000..6d08f61 --- /dev/null +++ b/lustre/tests/llapi_fid_test.c @@ -0,0 +1,733 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + * GPL HEADER END + */ + +/* + * Copyright 2014 Cray Inc, all rights reserved. + * Author: Frank Zago. + * + * A few portions are extracted from llapi_layout_test.c + * + * The purpose of this test is to test the llapi fid related function + * (fid2path, path2fid, ...) + * + * The program will exit as soon a non zero error code is returned. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define ERROR(fmt, ...) \ + fprintf(stderr, "%s: %s:%d: %s: " fmt "\n", \ + program_invocation_short_name, __FILE__, __LINE__, \ + __func__, ## __VA_ARGS__); + +#define DIE(fmt, ...) \ + do { \ + ERROR(fmt, ## __VA_ARGS__); \ + exit(EXIT_FAILURE); \ + } while (0) + +#define ASSERTF(cond, fmt, ...) \ + do { \ + if (!(cond)) \ + DIE("assertion '%s' failed: "fmt, \ + #cond, ## __VA_ARGS__); \ + } while (0) + +#define PERFORM(testfn) \ + do { \ + cleanup(); \ + fprintf(stderr, "Starting test " #testfn " at %lld\n", \ + (unsigned long long)time(NULL)); \ + testfn(); \ + fprintf(stderr, "Finishing test " #testfn " at %lld\n", \ + (unsigned long long)time(NULL)); \ + cleanup(); \ + } while (0) + +/* Name of file/directory. Will be set once and will not change. */ +static char mainpath[PATH_MAX]; +static const char *maindir = "llapi_fid_test_name_9585766"; + +static char fsmountdir[PATH_MAX]; /* Lustre mountpoint */ +static char *lustre_dir; /* Test directory inside Lustre */ + +/* Cleanup our test directory. */ +static void cleanup(void) +{ + char cmd[PATH_MAX]; + int rc; + + rc = snprintf(cmd, sizeof(cmd), "rm -rf -- '%s'", mainpath); + ASSERTF(rc > 0 && rc < sizeof(cmd), + "invalid delete command for path '%s'", mainpath); + system(cmd); +} + +/* Helper - call path2fid, fd2fid and fid2path against an existing + * file/directory */ +static void helper_fid2path(const char *filename, int fd) +{ + lustre_fid fid; + lustre_fid fid2; + lustre_fid fid3; + char fidstr[FID_LEN]; + char path1[PATH_MAX]; + char path2[PATH_MAX]; + char path3[PATH_MAX]; + long long recno1; + long long recno2; + int linkno1; + int linkno2; + int rc; + + rc = llapi_path2fid(filename, &fid); + ASSERTF(rc == 0, "llapi_path2fid failed for '%s': %s", + filename, strerror(-rc)); + + /* Without braces */ + snprintf(fidstr, sizeof(fidstr), DFID_NOBRACE, PFID(&fid)); + recno1 = -1; + linkno1 = 0; + rc = llapi_fid2path(lustre_dir, fidstr, path1, + sizeof(path1), &recno1, &linkno1); + ASSERTF(rc == 0, "llapi_fid2path failed for fid %s: %s", + fidstr, strerror(-rc)); + + /* Same with braces */ + snprintf(fidstr, sizeof(fidstr), DFID, PFID(&fid)); + recno2 = -1; + linkno2 = 0; + rc = llapi_fid2path(lustre_dir, fidstr, path2, + sizeof(path2), &recno2, &linkno2); + ASSERTF(rc == 0, "llapi_fid2path failed for fid %s: %s", + fidstr, strerror(-rc)); + + /* Make sure both calls to llapi_fid2path returned the same + * data. */ + ASSERTF(strcmp(path1, path2) == 0, "paths are different: '%s' / '%s'", + path1, path2); + ASSERTF(recno1 == recno2, "recnos are different: %lld / %lld", + recno1, recno2); + ASSERTF(linkno1 == linkno2, "linknos are different: %d / %d", + linkno1, linkno2); + + /* Try fd2fid and check that the result is still the same. */ + if (fd != -1) { + rc = llapi_fd2fid(fd, &fid3); + ASSERTF(rc == 0, "llapi_fd2fid failed for '%s': %s", + mainpath, strerror(-rc)); + + ASSERTF(memcmp(&fid, &fid3, sizeof(fid)) == 0, + "fids are different"); + } + + /* Pass the result back to fid2path and ensure the fid stays + * the same. */ + rc = snprintf(path3, sizeof(path3), "%s/%s", fsmountdir, path1); + ASSERTF((rc > 0 && rc < sizeof(path3)), "invalid name"); + rc = llapi_path2fid(path3, &fid2); + ASSERTF(rc == 0, "llapi_path2fid failed for '%s': %s", + path3, strerror(-rc)); + ASSERTF(memcmp(&fid, &fid2, sizeof(fid)) == 0, "fids are different"); +} + +/* Test helper_fid2path */ +static void test10(void) +{ + int rc; + int fd; + struct stat statbuf; + + /* Against Lustre root */ + helper_fid2path(lustre_dir, -1); + + /* Against a regular file */ + fd = creat(mainpath, 0); + ASSERTF(fd >= 0, "creat failed for '%s': %s", + mainpath, strerror(errno)); + helper_fid2path(mainpath, fd); + close(fd); + rc = unlink(mainpath); + ASSERTF(rc == 0, "unlink failed for '%s': %s", + mainpath, strerror(errno)); + + /* Against a pipe */ + rc = mkfifo(mainpath, 0); + ASSERTF(rc == 0, "mkfifo failed for '%s': %s", + mainpath, strerror(errno)); + helper_fid2path(mainpath, -1); + rc = unlink(mainpath); + ASSERTF(rc == 0, "unlink failed for '%s': %s", + mainpath, strerror(errno)); + + /* Against a directory */ + rc = mkdir(mainpath, 0); + ASSERTF(rc == 0, "mkdir failed for '%s': %s", + mainpath, strerror(errno)); + helper_fid2path(mainpath, -1); + rc = rmdir(mainpath); + ASSERTF(rc == 0, "rmdir failed for '%s': %s", + mainpath, strerror(errno)); + + /* Against a char device. Use same as /dev/null in case things + * go wrong. */ + rc = stat("/dev/null", &statbuf); + ASSERTF(rc == 0, "stat failed for /dev/null: %s", strerror(errno)); + rc = mknod(mainpath, S_IFCHR, statbuf.st_rdev); + ASSERTF(rc == 0, "mknod failed for '%s': %s", + mainpath, strerror(errno)); + helper_fid2path(mainpath, -1); + rc = unlink(mainpath); + ASSERTF(rc == 0, "unlink failed for '%s': %s", + mainpath, strerror(errno)); + + /* Against a block device device. Reuse same dev. */ + rc = mknod(mainpath, S_IFBLK, statbuf.st_rdev); + ASSERTF(rc == 0, "mknod failed for '%s': %s", + mainpath, strerror(errno)); + helper_fid2path(mainpath, -1); + rc = unlink(mainpath); + ASSERTF(rc == 0, "unlink failed for '%s': %s", + mainpath, strerror(errno)); + + /* Against a socket. */ + rc = mknod(mainpath, S_IFSOCK, (dev_t)0); + ASSERTF(rc == 0, "mknod failed for '%s': %s", + mainpath, strerror(errno)); + helper_fid2path(mainpath, -1); + rc = unlink(mainpath); + ASSERTF(rc == 0, "unlink failed for '%s': %s", + mainpath, strerror(errno)); +} + +/* Test against deleted files. */ +static void test11(void) +{ + int rc; + int fd; + lustre_fid fid; + char fidstr[FID_LEN]; + char path[PATH_MAX]; + long long recno; + int linkno; + + /* Against a regular file */ + fd = creat(mainpath, 0); + ASSERTF(fd >= 0, "creat failed for '%s': %s", + mainpath, strerror(errno)); + close(fd); + + rc = llapi_path2fid(mainpath, &fid); + ASSERTF(rc == 0, "llapi_path2fid failed for '%s': %s", + mainpath, strerror(-rc)); + + rc = unlink(mainpath); + ASSERTF(rc == 0, "unlink failed for '%s': %s", + mainpath, strerror(errno)); + + snprintf(fidstr, sizeof(fidstr), DFID_NOBRACE, PFID(&fid)); + recno = -1; + linkno = 0; + rc = llapi_fid2path(lustre_dir, fidstr, path, + sizeof(path), &recno, &linkno); + ASSERTF(rc == -ENOENT, "llapi_fid2path failed for fid %s: %s", + fidstr, strerror(-rc)); +} + +/* Test volatile file. */ +static void test12(void) +{ + int rc; + int fd; + int fd2; + int fd3; + lustre_fid fid; + + /* Against a volatile file */ + rc = mkdir(mainpath, 0); + ASSERTF(rc == 0, "mkdir failed for '%s': %s", + mainpath, strerror(errno)); + fd = llapi_create_volatile_idx(mainpath, -1, 0600); + ASSERTF(fd >= 0, "creat failed for '%s': %s", + mainpath, strerror(errno)); + + rc = llapi_fd2fid(fd, &fid); + ASSERTF(rc == 0, "llapi_path2fid failed for '%s': %s", + mainpath, strerror(-rc)); + + /* No many ways to test, except to open by fid. */ + fd2 = llapi_open_by_fid(mainpath, &fid, 0600); + ASSERTF(fd2 >= 0, "llapi_open_by_fid for " DFID_NOBRACE ": %s", + PFID(&fid), strerror(errno)); + + close(fd); + + /* Check the file can still be opened, since fd2 is not + * closed. */ + fd3 = llapi_open_by_fid(mainpath, &fid, 0600); + ASSERTF(fd3 >= 0, "llapi_open_by_fid for " DFID_NOBRACE ": %s", + PFID(&fid), strerror(errno)); + + close(fd2); + close(fd3); + + /* The volatile file is gone now. */ + fd = llapi_open_by_fid(mainpath, &fid, 0600); + ASSERTF(fd < 0, "llapi_open_by_fid for " DFID_NOBRACE ": %d", + PFID(&fid), fd); +} + +/* Test with sub directories */ +static void test20(void) +{ + char testpath[PATH_MAX]; + size_t len; + int dir_created = 0; + int rc; + + rc = snprintf(testpath, sizeof(testpath), "%s", mainpath); + ASSERTF((rc > 0 && rc < sizeof(testpath)), + "invalid name for testpath '%s'", mainpath); + + rc = mkdir(testpath, S_IRWXU); + ASSERTF(rc == 0, "mkdir failed for '%s': %s", + testpath, strerror(errno)); + + len = strlen(testpath); + + /* Create subdirectories as long as we can. Each new subdir is + * "/x", so we need at least 3 characters left in testpath. */ + while (len <= sizeof(testpath) - 3) { + strncat(testpath, "/x", 2); + + len += 2; + + rc = mkdir(testpath, S_IRWXU); + ASSERTF(rc == 0, "mkdir failed for '%s': %s", + testpath, strerror(errno)); + + dir_created++; + + helper_fid2path(testpath, -1); + } + + /* And test the last one. */ + helper_fid2path(testpath, -1); + + /* Make sure we have created enough directories. Even with a + * reasonably long mountpath, we should have created at least + * 2000. */ + ASSERTF(dir_created >= 2000, "dir_created=%d -- '%s'", + dir_created, testpath); +} + +/* Test linkno from fid2path */ +static void test30(void) +{ + /* Note that since the links are stored in the extended + * attributes, only a few of these will fit (about 150 in this + * test). Still, create more than that to ensure the system + * doesn't break. See LU-5746. */ + const int num_links = 1000; + struct { + char filename[PATH_MAX]; + bool seen; + } links[num_links]; + char buf[PATH_MAX]; + char buf2[PATH_MAX]; + lustre_fid fid; + char fidstr[FID_LEN]; + int rc; + int i; + int j; + int fd; + int linkno; + bool past_link_limit = false; + + /* Create the containing directory. */ + rc = mkdir(mainpath, 0); + ASSERTF(rc == 0, "mkdir failed for '%s': %s", + mainpath, strerror(errno)); + + /* Initializes the link array. */ + for (i = 0; i < num_links; i++) { + rc = snprintf(links[i].filename, sizeof(links[i].filename), + "%s/%s/link%04d", lustre_dir, maindir, i); + + ASSERTF((rc > 0 && rc < sizeof(links[i].filename)), + "invalid name for link"); + + links[i].seen = false; + } + + /* Create the original file. */ + fd = creat(links[0].filename, 0); + ASSERTF(fd >= 0, "create failed for '%s': %s", + links[0].filename, strerror(errno)); + close(fd); + + rc = llapi_path2fid(links[0].filename, &fid); + ASSERTF(rc == 0, "llapi_path2fid failed for '%s': %s", + links[0].filename, strerror(-rc)); + snprintf(fidstr, sizeof(fidstr), DFID_NOBRACE, PFID(&fid)); + + /* Create the links */ + for (i = 1; i < num_links; i++) { + rc = link(links[0].filename, links[i].filename); + ASSERTF(rc == 0, "link failed for '%s' / '%s': %s", + links[0].filename, links[i].filename, strerror(errno)); + } + + /* Query the links, making sure we got all of them */ + for (i = 0; i < num_links + 10; i++) { + long long recno; + bool found; + + /* Without braces */ + recno = -1; + linkno = i; + rc = llapi_fid2path(links[0].filename, fidstr, buf, + sizeof(buf), &recno, &linkno); + ASSERTF(rc == 0, "llapi_fid2path failed for fid %s: %s", + fidstr, strerror(-rc)); + + snprintf(buf2, sizeof(buf2), "%s/%s", fsmountdir, buf); + + if (past_link_limit == false) { + /* Find the name in the links that were created */ + found = false; + for (j = 0; j < num_links; j++) { + if (strcmp(buf2, links[j].filename) == 0) { + ASSERTF(links[j].seen == false, + "link '%s' already seen", + links[j].filename); + links[j].seen = true; + found = true; + break; + } + } + ASSERTF(found == true, "link '%s' not found", buf2); + + if (linkno == i) { + /* The linkno hasn't changed. This + * means it is the last entry + * stored. */ + past_link_limit = true; + + fprintf(stderr, + "Was able to store %d links in the EA\n", + i); + + /* Also assume that some links were + * returned. It's hard to compute the + * exact value. */ + ASSERTF(i > 50, + "not enough links were returned: %d", + i); + } + } else { + /* Past the number of links stored in the EA, + * Lustre will simply return the original + * file. */ + ASSERTF(strcmp(buf2, links[0].filename) == 0, + "unexpected link for record %d: '%s' / '%s'", + i, buf2, links[0].filename); + } + + } +} + +/* Test llapi_fd2parent/llapi_path2parent on mainpath (whatever its + * type). mainpath must exist. */ +static void help_test40(void) +{ + lustre_fid parent_fid; + lustre_fid fid2; + char buf[PATH_MAX]; + int rc; + + /* Successful call */ + memset(buf, 0x55, sizeof(buf)); + rc = llapi_path2parent(mainpath, 0, &parent_fid, buf, PATH_MAX); + ASSERTF(rc == 0, "llapi_path2parent failed for '%s': %s", + mainpath, strerror(errno)); + ASSERTF(strcmp(buf, maindir) == 0, "paths are different: '%s' / '%s'", + buf, maindir); + + /* By construction, mainpath is just under lustre_dir, so we + * can check that the parent fid of mainpath is indeed the one + * of lustre_dir. */ + rc = llapi_path2fid(lustre_dir, &fid2); + ASSERTF(rc == 0, "llapi_path2fid failed for '%s': %s", + lustre_dir, strerror(-rc)); + ASSERTF(memcmp(&parent_fid, &fid2, sizeof(fid2)) == 0, + "fids are different"); + + /* Name too short */ + rc = llapi_path2parent(mainpath, 0, &parent_fid, buf, 0); + ASSERTF(rc == -EOVERFLOW, "llapi_path2parent error: %s", strerror(-rc)); + + rc = llapi_path2parent(mainpath, 0, &parent_fid, buf, 5); + ASSERTF(rc == -EOVERFLOW, "llapi_path2parent error: %s", strerror(-rc)); + + rc = llapi_path2parent(mainpath, 0, &parent_fid, buf, strlen(maindir)); + ASSERTF(rc == -EOVERFLOW, "llapi_path2parent error: %s", strerror(-rc)); + + rc = llapi_path2parent(mainpath, 0, &parent_fid, buf, + strlen(maindir)+1); + ASSERTF(rc == 0, "llapi_path2parent failed: %s", strerror(-rc)); +} + +static void test40(void) +{ + int fd; + int rc; + + /* Against a directory. */ + rc = mkdir(mainpath, 0); + ASSERTF(rc == 0, "mkdir failed for '%s': %s", + mainpath, strerror(errno)); + help_test40(); + + cleanup(); + + /* Against a regular file */ + fd = creat(mainpath, 0); + ASSERTF(fd >= 0, "creat failed for '%s': %s", + mainpath, strerror(errno)); + close(fd); +} + +/* Test LL_IOC_GETPARENT directly */ +static void test41(void) +{ + int rc; + int fd; + int i; + union { + struct getparent gp; + char buf[1024]; + } u; + + /* Against a regular file */ + fd = creat(mainpath, 0); + ASSERTF(fd >= 0, "creat failed for '%s': %s", + mainpath, strerror(errno)); + + /* Ask a few times */ + for (i = 0; i < 256; i++) { + memset(u.buf, i, sizeof(u.buf)); /* poison */ + u.gp.gp_linkno = 0; + u.gp.gp_name_size = 100; + + rc = ioctl(fd, LL_IOC_GETPARENT, &u.gp); + ASSERTF(rc == 0, "LL_IOC_GETPARENT failed: %s, rc=%d", + strerror(errno), rc); + ASSERTF(strcmp(u.gp.gp_name, maindir) == 0, + "strings are different: %zd, %zd", + strlen(u.gp.gp_name), strlen(maindir)); + } + + close(fd); +} + +/* Test with linkno. Create sub directories, and put a link to the + * original file in them. */ +static void test42(void) +{ + + const int num_links = 100; + struct { + char subdir[PATH_MAX]; + lustre_fid subdir_fid; + char filename[PATH_MAX]; + bool seen; + } links[num_links]; + char link0[PATH_MAX]; + char buf[PATH_MAX]; + int rc; + int i; + int fd; + int linkno; + lustre_fid parent_fid; + + /* Create the containing directory. */ + rc = mkdir(mainpath, 0); + ASSERTF(rc == 0, "mkdir failed: for '%s': %s", + mainpath, strerror(errno)); + + /* Initializes the link array. */ + for (i = 0; i < num_links; i++) { + rc = snprintf(links[i].subdir, sizeof(links[i].subdir), + "%s/sub%04d", mainpath, i); + ASSERTF((rc > 0 && rc < sizeof(links[i].subdir)), + "invalid name for subdir"); + + rc = snprintf(links[i].filename, sizeof(links[i].filename), + "link%04d", i); + ASSERTF((rc > 0 && rc < sizeof(links[i].filename)), + "invalid name for link"); + + links[i].seen = false; + } + + /* Create the subdirectories. */ + for (i = 0; i < num_links; i++) { + rc = mkdir(links[i].subdir, S_IRWXU); + ASSERTF(rc == 0, "mkdir failed for '%s': %s", + links[i].subdir, strerror(errno)); + + rc = llapi_path2fid(links[i].subdir, &links[i].subdir_fid); + ASSERTF(rc == 0, "llapi_path2fid failed for '%s': %s", + links[i].subdir, strerror(-rc)); + } + + /* Create the original file. */ + rc = snprintf(link0, sizeof(link0), "%s/%s", + links[0].subdir, links[0].filename); + ASSERTF((rc > 0 && rc < sizeof(link0)), "invalid name for file"); + + fd = creat(link0, 0); + ASSERTF(fd >= 0, "create failed for '%s': %s", link0, strerror(errno)); + close(fd); + + /* Create the links */ + for (i = 1; i < num_links; i++) { + rc = snprintf(buf, sizeof(buf), "%s/%s", + links[i].subdir, links[i].filename); + ASSERTF((rc > 0 && rc < sizeof(buf)), + "invalid name for link %d", i); + + rc = link(link0, buf); + ASSERTF(rc == 0, "link failed for '%s' / '%s': %s", + link0, buf, strerror(errno)); + } + + /* Query the links, making sure we got all of them. Do it in + * reverse order, just because! */ + for (linkno = num_links-1; linkno >= 0; linkno--) { + bool found; + + rc = llapi_path2parent(link0, linkno, &parent_fid, buf, + sizeof(buf)); + ASSERTF(rc == 0, "llapi_path2parent failed for '%s': %s", + link0, strerror(-rc)); + + /* Find the name in the links that were created */ + found = false; + for (i = 0; i < num_links; i++) { + if (memcmp(&parent_fid, &links[i].subdir_fid, + sizeof(parent_fid)) != 0) + continue; + + ASSERTF(strcmp(links[i].filename, buf) == 0, + "name differ: '%s' / '%s'", + links[i].filename, buf); + ASSERTF(links[i].seen == false, + "link '%s' already seen", links[i].filename); + links[i].seen = true; + found = true; + break; + } + ASSERTF(found == true, "link '%s' not found", buf); + } + + /* check non existent n+1 link */ + rc = llapi_path2parent(link0, num_links, &parent_fid, buf, sizeof(buf)); + ASSERTF(rc == -ENODATA, "llapi_path2parent error for '%s': %s", + link0, strerror(-rc)); +} + +static void usage(char *prog) +{ + fprintf(stderr, "Usage: %s [-d lustre_dir]\n", prog); + exit(EXIT_FAILURE); +} + +static void process_args(int argc, char *argv[]) +{ + int c; + + while ((c = getopt(argc, argv, "d:")) != -1) { + switch (c) { + case 'd': + lustre_dir = optarg; + break; + case '?': + default: + fprintf(stderr, "Unknown option '%c'\n", optopt); + usage(argv[0]); + } + } +} + +int main(int argc, char *argv[]) +{ + char fsname[8]; + int rc; + + process_args(argc, argv); + if (lustre_dir == NULL) + lustre_dir = "/mnt/lustre"; + + rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname); + if (rc != 0) { + fprintf(stderr, "Error: %s: not a Lustre filesystem\n", + lustre_dir); + return EXIT_FAILURE; + } + + /* Play nice with Lustre test scripts. Non-line buffered output + * stream under I/O redirection may appear incorrectly. */ + setvbuf(stdout, NULL, _IOLBF, 0); + + /* Create a test filename and reuse it. Remove possibly old files. */ + rc = snprintf(mainpath, sizeof(mainpath), "%s/%s", lustre_dir, maindir); + ASSERTF((rc > 0 && rc < sizeof(mainpath)), "invalid name for mainpath"); + cleanup(); + + atexit(cleanup); + + PERFORM(test10); + PERFORM(test11); + PERFORM(test12); + PERFORM(test20); + PERFORM(test30); + PERFORM(test40); + PERFORM(test41); + PERFORM(test42); + + return EXIT_SUCCESS; +} diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index a45f185..9ac5f84 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -9913,6 +9913,16 @@ test_154f() { } run_test 154f "get parent fids by reading link ea" +test_154g() +{ + [[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.6.92) ]] || + { skip "Need MDS version at least 2.6.92"; return 0; } + + mkdir -p $DIR/$tdir + llapi_fid_test -d $DIR/$tdir +} +run_test 154g "various llapi FID tests" + test_155_small_load() { local temp=$TMP/$tfile local file=$DIR/$tfile