Skip to content

Instantly share code, notes, and snippets.

@nedbass
Last active December 12, 2015 07:19
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save nedbass/4736037 to your computer and use it in GitHub Desktop.
Test suite for llapi_layout interface.
/*
* These tests exercise the llapi_layout API which abstracts the layout
* of a Lustre file behind an opaque data type. They assume a Lustre file
* system with at least 6 OSTs and a pool names "testpool" containing 6
* OSTs. For example,
*
* sudo lctl pool_new lustre.testpool
* sudo lctl pool_add lustre.testpool OST[0-5]
* gcc -D LUSTRE_DIR=\"/mnt/lustre/somedir\" -Wall -g -Werror -o test test.c \
* -llustrepapi
* sudo ./test
*
* Written by: Ned Bass <bass6@llnl.gov>
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <lustre/lustreapi.h>
#include <pwd.h>
#include <sys/stat.h>
#define TEST(testfn) { test(&(testfn), #testfn); }
#ifndef LUSTRE_DIR
#define LUSTRE_DIR "/mnt/lustre"
#endif
#define TEST_POOL_NAME "testpool"
/* This function runs a single test by forking the process. This way,
if there is a segfault during a test, the test program won't crash */
void test(void (*testfn)(), const char *name) {
pid_t pid = fork();
if (pid > 0) {
/* Check the child's return value */
int status = 0;
wait(&status);
/* Non-zero value = test failed */
printf("%s:\t%s\n", name, status ? "fail" : "pass");
} else if (pid == 0) {
/* Run the test in the child process. Exit with 0 for success,
non-zero for failure */
testfn();
exit(0);
} else {
printf("Fork failed!\n");
}
}
#define T1FILE LUSTRE_DIR "/t1"
#define T1_STRIPE_COUNT 5
#define T1_STRIPE_SIZE 1048576
#define T1_OST_OFFSET 3
/* Sanity test. Read and write layout attributes then create a new file. */
void test1()
{
int rc;
lustre_layout_t *layout = llapi_layout_alloc();
assert(layout != NULL);
rc = unlink(T1FILE);
assert(rc == 0 || errno == ENOENT);
assert(llapi_layout_stripe_count_set(layout, T1_STRIPE_COUNT) == 0);
assert(llapi_layout_stripe_count(layout) == T1_STRIPE_COUNT);
assert(llapi_layout_stripe_size_set(layout, T1_STRIPE_SIZE) == 0);
assert(llapi_layout_stripe_size(layout) == T1_STRIPE_SIZE);
assert(llapi_layout_pool_name_set(layout, TEST_POOL_NAME) == 0);
assert(strcmp(llapi_layout_pool_name(layout), TEST_POOL_NAME) == 0);
rc = llapi_layout_ost_index_set(layout, 0, T1_OST_OFFSET);
assert(rc == 0);
rc = llapi_layout_file_create(layout, T1FILE, 0660, 0);
assert(rc >= 0);
assert(close(rc) == 0);
llapi_layout_free(layout);
}
void __test2_helper(lustre_layout_t *layout)
{
int ost0;
int ost1;
int obj0;
int obj1;
assert(llapi_layout_stripe_count(layout) == T1_STRIPE_COUNT);
assert(llapi_layout_stripe_size(layout) == T1_STRIPE_SIZE);
ost0 = llapi_layout_ost_index(layout, 0);
ost1 = llapi_layout_ost_index(layout, 1);
obj0 = llapi_layout_obj_id(layout, 0);
obj1 = llapi_layout_obj_id(layout, 1);
/* FIXME setting pool name works for ioctl but not fsetxattr :( */
assert(strcmp(llapi_layout_pool_name(layout), TEST_POOL_NAME) == 0);
assert(ost0 == T1_OST_OFFSET);
assert(ost1 != ost0);
assert(obj0 != 0);
assert(obj1 != 0);
}
/* Read back file layout from test1 by path and verify attributes. */
void test2()
{
errno = 0;
lustre_layout_t *layout = llapi_layout_lookup_bypath(T1FILE);
assert(layout != NULL);
assert(errno == 0);
__test2_helper(layout);
llapi_layout_free(layout);
}
/* Read back file layout from test1 by open fd and verify attributes. */
void test3()
{
int fd;
fd = open(T1FILE, O_RDONLY);
assert(fd != -1);
errno = 0;
lustre_layout_t *layout = llapi_layout_lookup_byfd(fd);
assert(close(fd) == 0);
assert(layout != NULL);
assert(errno == 0);
__test2_helper(layout);
llapi_layout_free(layout);
}
#define T4FILE LUSTRE_DIR "/t4"
#define T4_STRIPE_COUNT 5
#define T4_STRIPE_SIZE 2097152
/* Create a file with 'lfs setstripe' then verify it's layout */
void test4()
{
int rc;
int ost0;
int ost1;
int obj0;
int obj1;
const char *lfs = getenv("LFS");
char cmd[4096];
if (lfs == NULL)
lfs = "/usr/bin/lfs";
rc = unlink(T4FILE);
assert(rc == 0 || errno == ENOENT);
snprintf(cmd, 4096, "%s setstripe -p %s -c %d -s %d %s\n", lfs,
TEST_POOL_NAME, T4_STRIPE_COUNT, T4_STRIPE_SIZE, T4FILE);
assert(system(cmd) == 0);
errno = 0;
lustre_layout_t *layout = llapi_layout_lookup_bypath(T4FILE);
assert(layout != NULL);
assert(errno == 0);
assert(llapi_layout_stripe_count(layout) == T4_STRIPE_COUNT);
assert(llapi_layout_stripe_size(layout) == T4_STRIPE_SIZE);
assert(strcmp(llapi_layout_pool_name(layout), TEST_POOL_NAME) == 0);
ost0 = llapi_layout_ost_index(layout, 0);
ost1 = llapi_layout_ost_index(layout, 1);
obj0 = llapi_layout_obj_id(layout, 0);
obj1 = llapi_layout_obj_id(layout, 1);
assert(ost0 != ost1);
assert(obj0 != 0);
assert(obj1 != 0);
llapi_layout_free(layout);
}
#define T5FILE LUSTRE_DIR "/t5"
/* llapi_layout_lookup_bypath() returns ENOENT in errno when expected. */
void test5()
{
int rc;
rc = unlink(T5FILE);
assert(rc == 0 || errno == ENOENT);
errno = 0;
lustre_layout_t *layout = llapi_layout_lookup_bypath(T5FILE);
assert(layout == NULL);
assert(errno == ENOENT);
}
/* llapi_layout_lookup_byfd() returns EBADF in errno when expected. */
void test6()
{
int rc;
rc = unlink(T5FILE);
assert(rc == 0 || errno == ENOENT);
errno = 0;
lustre_layout_t *layout = llapi_layout_lookup_byfd(9999);
assert(layout == NULL);
assert(errno == EBADF);
}
#define T7FILE LUSTRE_DIR "/t7"
/* llapi_layout_lookup_bypath() returns EACCES in errno when expected. */
void test7()
{
int fd;
int rc;
uid_t myuid = getuid();
assert(myuid == 0); /* Need root for this test. */
/* Create file as root */
rc = unlink(T7FILE);
assert(rc == 0 || errno == ENOENT);
fd = open(T7FILE, O_CREAT);
assert(fd != -1);
assert(fchmod(fd, 0400) == 0);
assert(close(fd) == 0);
/* Become unprivileged user */
struct passwd *pw = getpwnam("nobody");
assert(pw != NULL);
assert(seteuid(pw->pw_uid) == 0);
errno = 0;
lustre_layout_t *layout = llapi_layout_lookup_bypath(T7FILE);
assert(layout == NULL);
assert(errno == EACCES);
assert(seteuid(myuid) == 0);
}
#define T8FILE LUSTRE_DIR "/t8"
/* llapi_layout_lookup_bypath() returns ENODATA in errno for file with no
* striping attributes. */
void test8()
{
int fd;
int rc;
lustre_layout_t *layout;
rc = unlink(T8FILE);
assert(rc == 0 || errno == ENOENT);
fd = open(T8FILE, O_CREAT, 0640);
assert(fd != -1);
assert(close(fd) == 0);
errno = 0;
layout = llapi_layout_lookup_bypath(T8FILE);
assert(layout == NULL);
assert(errno == ENODATA);
}
#define T10FILE LUSTRE_DIR "/t10"
#define T10_STRIPE_COUNT 2
#define T10_STRIPE_SIZE 1048576
/* llapi_layout_create_file() returns EEXIST in errno for
* already-existing file. */
void test10()
{
int rc;
int fd;
lustre_layout_t *layout;
(void) unlink(T10FILE);
layout = llapi_layout_alloc();
llapi_layout_stripe_count_set(layout, T10_STRIPE_COUNT);
llapi_layout_stripe_size_set(layout, T10_STRIPE_SIZE);
fd = llapi_layout_file_create(layout, T10FILE, 0750, 0);
assert(fd >= 0);
assert(close(fd) == 0);
rc = llapi_layout_file_create(layout, T10FILE, 0750, 0);
assert(rc < 0);
assert(errno == EEXIST);
llapi_layout_free(layout);
}
/* Verify stripe_count interfaces return errors as expected */
void test11()
{
int rc;
lustre_layout_t *layout;
layout = llapi_layout_alloc();
assert(layout != NULL);
/* stripe count less than -1 (-1 means use all available OSTs) */
errno = 0;
rc = llapi_layout_stripe_count_set(layout, -2);
assert(rc == -1);
assert(errno = EINVAL);
/* NULL layout */
errno = 0;
rc = llapi_layout_stripe_count_set(NULL, 2);
assert(rc == -1);
assert(errno = EINVAL);
/* NULL layout */
errno = 0;
rc = llapi_layout_stripe_count(NULL);
assert(rc == -1);
assert(errno = EINVAL);
/* stripe count too large */
errno = 0;
rc = llapi_layout_stripe_count_set(layout, LOV_MAX_STRIPE_COUNT + 1);
assert(rc == -1);
assert(errno = EINVAL);
llapi_layout_free(layout);
}
/* Verify stripe_size interfaces return errors as expected */
void test12()
{
int rc;
lustre_layout_t *layout;
layout = llapi_layout_alloc();
assert(layout != NULL);
/* negative stripe size */
errno = 0;
rc = llapi_layout_stripe_size_set(layout, -1);
assert(rc == -1);
assert(errno = EINVAL);
/* stripe size too big */
errno = 0;
rc = llapi_layout_stripe_size_set(layout, 1ULL << 32);
assert(rc == -1);
assert(errno = EINVAL);
/* NULL layout */
errno = 0;
rc = llapi_layout_stripe_size_set(NULL, 1048576);
assert(rc == -1);
assert(errno = EINVAL);
/* NULL layout */
errno = 0;
rc = llapi_layout_stripe_size(NULL);
assert(rc == -1);
assert(errno = EINVAL);
llapi_layout_free(layout);
}
/* Verify pool_name interfaces return errors as expected */
void test13()
{
int rc;
lustre_layout_t *layout;
const char *poolname;
layout = llapi_layout_alloc();
assert(layout != NULL);
/* NULL layout */
errno = 0;
rc = llapi_layout_pool_name_set(NULL, "foo");
assert(rc == -1);
assert(errno = EINVAL);
/* NULL pool name */
errno = 0;
rc = llapi_layout_pool_name_set(layout, NULL);
assert(rc == -1);
assert(errno = EINVAL);
/* NULL layout */
errno = 0;
poolname = llapi_layout_pool_name(NULL);
assert(poolname == NULL);
assert(errno = EINVAL);
llapi_layout_free(layout);
}
#define T14FILE LUSTRE_DIR "/t14"
#define T14_STRIPE_COUNT 2
/* Verify ost_index interfaces return errors as expected */
void test14()
{
int rc;
lustre_layout_t *layout;
layout = llapi_layout_alloc();
assert(layout != NULL);
/* Only setting OST index for stripe 0 is supported for now. */
errno = 0;
rc = llapi_layout_ost_index_set(layout, 1, 1);
assert(rc == -1);
assert(errno = EOPNOTSUPP);
/* OST index less than -1 (-1 means let MDS choose) */
errno = 0;
rc = llapi_layout_ost_index_set(layout, 0, -2);
assert(rc == -1);
assert(errno = EINVAL);
/* NULL layout */
errno = 0;
rc = llapi_layout_ost_index_set(NULL, 0, 1);
assert(rc == -1);
assert(errno = EINVAL);
/* NULL layout */
errno = 0;
rc = llapi_layout_ost_index(NULL, 0);
assert(rc == -1);
assert(errno = EINVAL);
/* Layout not read from file so has no OST data. */
errno = 0;
rc = llapi_layout_ost_index(layout, 0);
assert(rc == -1);
assert(errno = EINVAL);
/* n greater than stripe count*/
rc = unlink(T14FILE);
assert(rc == 0 || errno == ENOENT);
assert(llapi_layout_stripe_count_set(layout, T14_STRIPE_COUNT) == 0);
rc = llapi_layout_file_create(layout, T14FILE, 0644, 0);
assert(rc >= 0);
close(rc);
llapi_layout_free(layout);
layout = llapi_layout_lookup_bypath(T14FILE);
errno = 0;
rc = llapi_layout_ost_index(layout, 3);
assert(rc == -1);
assert(errno = EINVAL);
llapi_layout_free(layout);
}
/* Verify llapi_layout_file_create() returns errors as expected */
void test15()
{
int rc;
/* NULL layout */
errno = 0;
rc = llapi_layout_file_create(NULL, "foo", 0, 0);
assert(rc == -1);
assert(errno == EINVAL);
}
#define T16FILE LUSTRE_DIR "/t16"
#define T16_STRIPE_COUNT 2
/* Can't change striping attributes of existing file. */
void test16()
{
int rc;
lustre_layout_t *layout;
rc = unlink(T16FILE);
assert(rc == 0 || errno == ENOENT);
errno = 0;
layout = llapi_layout_alloc();
assert(layout != NULL);
assert(llapi_layout_stripe_count_set(layout, T16_STRIPE_COUNT) == 0);
rc = llapi_layout_file_create(layout, T16FILE, 0640, 0);
assert(rc >= 0);
assert(errno == 0);
assert(close(rc) == 0);
assert(llapi_layout_stripe_count_set(layout, T16_STRIPE_COUNT + 1) == 0);
rc = llapi_layout_file_create(layout, T16FILE, 0640, 0);
assert(rc < 0);
assert(errno == EEXIST);
llapi_layout_free(layout);
layout = llapi_layout_lookup_bypath(T16FILE);
assert(layout != NULL);
assert(llapi_layout_stripe_count(layout) == T16_STRIPE_COUNT);
llapi_layout_free(layout);
}
#define T17FILE LUSTRE_DIR "/t17"
/* Default stripe attributes are applied as expected. */
void test17()
{
int rc;
lustre_layout_t *dirlayout;
lustre_layout_t *filelayout;
rc = unlink(T17FILE);
assert(rc == 0 || errno == ENOENT);
assert(dirlayout = llapi_layout_lookup_bypath(LUSTRE_DIR));
assert(filelayout = llapi_layout_alloc());
rc = llapi_layout_file_create(filelayout, T17FILE, 0640, 0);
assert(rc >= 0);
assert(close(rc) == 0);
llapi_layout_free(filelayout);
assert(filelayout = llapi_layout_lookup_bypath(T17FILE));
assert(llapi_layout_stripe_count(filelayout) ==
llapi_layout_stripe_count(dirlayout));
assert(llapi_layout_stripe_size(filelayout) ==
llapi_layout_stripe_size(dirlayout));
llapi_layout_free(filelayout);
llapi_layout_free(dirlayout);
}
#define T18FILE LUSTRE_DIR "/t18"
/* Setting stripe count to -1 uses all available OSTs. */
void test18()
{
int rc;
int fd;
int ost_count;
lustre_layout_t *layout;
rc = unlink(T18FILE);
assert(rc == 0 || errno == ENOENT);
assert(layout = llapi_layout_alloc());
llapi_layout_stripe_count_set(layout, -1);
rc = llapi_layout_file_create(layout, T18FILE, 0640, 0);
assert(rc >= 0);
assert(close(rc) == 0);
llapi_layout_free(layout);
/* Get number of available OSTs */
fd = open(T18FILE, O_RDONLY);
assert(fd != -1);
llapi_lov_get_uuids(fd, NULL, &ost_count);
assert(close(fd) == 0);
assert(layout = llapi_layout_lookup_bypath(T18FILE));
assert(llapi_layout_stripe_count(layout) == ost_count);
llapi_layout_free(layout);
}
void sigsegv(int signal) {
printf("Segmentation fault\n");
exit(1);
}
int main(int argc, char *argv[]) {
signal(SIGSEGV, sigsegv);
TEST(test1);
TEST(test2);
TEST(test3);
TEST(test4);
TEST(test5);
TEST(test6);
TEST(test7);
TEST(test8);
TEST(test10);
TEST(test11);
TEST(test12);
TEST(test13);
TEST(test14);
TEST(test15);
TEST(test16);
TEST(test17);
TEST(test18);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment