*/
/*
- * Copyright 2014 Cray Inc, all rights reserved.
+ * Copyright 2014, 2015 Cray Inc, all rights reserved.
* Author: Frank Zago.
*
* A few portions are extracted from llapi_layout_test.c
#include <errno.h>
#include <getopt.h>
#include <fcntl.h>
+#include <sys/ioctl.h>
#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/uio.h>
#include <sys/stat.h>
+#include <time.h>
#include <unistd.h>
#include <poll.h>
#include <lustre/lustreapi.h>
-#include <lustre/lustre_idl.h>
#define ERROR(fmt, ...) \
fprintf(stderr, "%s: %s:%d: %s: " fmt "\n", \
#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. */
int gid;
int i;
- cleanup();
-
/* Create the test file, and open it. */
fd = creat(mainpath, 0);
ASSERTF(fd >= 0, "creat failed for '%s': %s",
int gid;
char buf[10000];
- cleanup();
-
/* Create the test file. */
fd = creat(mainpath, 0);
ASSERTF(fd >= 0, "creat failed for '%s': %s",
close(fd);
}
+}
- cleanup();
+/* Lock / unlock a volatile file, with different creation flags */
+static void test12(void)
+{
+ int rc;
+ int fd;
+ int gid;
+
+ rc = mkdir(mainpath, 0600);
+ ASSERTF(rc == 0, "mkdir failed for '%s': %s",
+ mainpath, strerror(errno));
+
+ fd = llapi_create_volatile_idx(mainpath, -1, O_CREAT | O_WRONLY);
+ ASSERTF(fd >= 0, "llapi_create_volatile_idx failed on '%s': %s",
+ mainpath, strerror(-fd));
+
+ gid = 34895;
+ rc = llapi_group_lock(fd, gid);
+ ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(-rc));
+
+ rc = llapi_group_unlock(fd, gid);
+ ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(-rc));
+
+ close(fd);
+
+ fd = llapi_create_volatile_idx(mainpath, -1,
+ O_CREAT | O_WRONLY | O_LOV_DELAY_CREATE);
+ ASSERTF(fd >= 0, "llapi_create_volatile_idx failed on '%s': %s",
+ mainpath, strerror(-fd));
+
+ gid = 3354895;
+ rc = llapi_group_lock(fd, gid);
+ ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(-rc));
+
+ rc = llapi_group_unlock(fd, gid);
+ ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(-rc));
+
+ close(fd);
+
+ fd = llapi_create_volatile_idx(mainpath, -1, O_RDONLY);
+ ASSERTF(fd >= 0, "llapi_create_volatile_idx failed on '%s': %s",
+ mainpath, strerror(-fd));
+
+ gid = 3489655;
+ rc = llapi_group_lock(fd, gid);
+ ASSERTF(rc == 0, "cannot lock '%s': %s", mainpath, strerror(-rc));
+
+ rc = llapi_group_unlock(fd, gid);
+ ASSERTF(rc == 0, "cannot unlock '%s': %s", mainpath, strerror(-rc));
+
+ close(fd);
}
static void helper_test20(int fd)
int rc;
char dname[PATH_MAX];
- cleanup();
-
/* Try the mountpoint. Should fail. */
fd = open(fsmountdir, O_RDONLY | O_DIRECTORY);
ASSERTF(fd >= 0, "open failed for '%s': %s", mainpath, strerror(errno));
/* A regular directory. */
rc = mkdir(mainpath, 0600);
- ASSERTF(fd >= 0, "mkdir failed for '%s': %s",
+ ASSERTF(rc == 0, "mkdir failed for '%s': %s",
mainpath, strerror(errno));
fd = open(mainpath, O_RDONLY | O_DIRECTORY);
int gid2;
int rc;
- cleanup();
-
/* Create the test file, and open it. */
fd1 = creat(mainpath, 0);
ASSERTF(fd1 >= 0, "open failed for '%s': %s",
close(fd2);
}
+/* Test locking between several fds. */
+static void test40(void)
+{
+ int rc;
+ int fd;
+ int gid;
+ char buf[10000];
+ int i, j, threads = 40;
+
+ /* Create the test file. */
+ fd = open(mainpath, O_RDWR | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ ASSERTF(fd >= 0, "creat failed for '%s': %s",
+ mainpath, strerror(errno));
+ /* Lock */
+ gid = 1234;
+ rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
+ ASSERTF(rc == 0, "cannot lock '%s' gid %d: %s", mainpath, gid,
+ strerror(errno));
+
+ for (i = 0; i < threads; i++) {
+ rc = fork();
+ ASSERTF(rc >= 0, "fork failed %s", strerror(errno));
+
+ if (rc == 0) {
+ struct iovec io = { .iov_base = buf,
+ .iov_len = sizeof(buf)};
+
+ /* writing to a fixed offset */
+ memset(buf, i, sizeof(buf));
+ rc = pwritev(fd, &io, 1, sizeof(buf) * i);
+ ASSERTF(rc == sizeof(buf), "write failed for '%s' block %d: %s",
+ mainpath, i, strerror(errno));
+
+ close(fd);
+ exit(0);
+ }
+ }
+
+ while ((i = wait(&rc)) > 0);
+
+ /* Check data */
+ for (i = 0; i < threads; i++) {
+ rc = read(fd, buf, sizeof(buf));
+ ASSERTF(rc == sizeof(buf), "read failed for '%s': %s",
+ mainpath, strerror(errno));
+ for (j = 0; j < rc; j++)
+ ASSERTF(i == buf[j], "wrong data at off %d %d != %d",
+ j, i, buf[j]);
+ }
+
+ /* close unlock group lock */
+ rc = close(fd);
+ ASSERTF(rc == 0, "close failed '%s': %s",
+ mainpath, strerror(errno));
+}
+
static void usage(char *prog)
{
fprintf(stderr, "Usage: %s [-d lustre_dir]\n", prog);
int main(int argc, char *argv[])
{
- char fsname[8];
+ char fsname[8 + 1];
int rc;
process_args(argc, argv);
PERFORM(test10);
PERFORM(test11);
+ PERFORM(test12);
PERFORM(test20);
PERFORM(test30);
+ PERFORM(test40);
return EXIT_SUCCESS;
}