Commit 0781cb33 authored by Pavel Begunkov's avatar Pavel Begunkov Committed by Andrei Vagin

zdtm: Add file lease tests

Test cases:
0. Basic non-breaking read/write leases.
1. Multiple read leases and OFDs with no lease for the same file.
2. Breaking leases.
3. Multiple fds (dup + inherited) for single lease (mutual OFD).
Signed-off-by: 's avatarPavel Begunkov <asml.silence@gmail.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 8038462d
...@@ -249,6 +249,10 @@ TST_FILE = \ ...@@ -249,6 +249,10 @@ TST_FILE = \
sockets00 \ sockets00 \
sockets03 \ sockets03 \
sockets_dgram \ sockets_dgram \
file_lease00 \
file_lease01 \
file_lease02 \
file_lease03 \
file_locks00 \ file_locks00 \
file_locks01 \ file_locks01 \
file_locks02 \ file_locks02 \
......
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include "zdtmtst.h"
const char *test_doc = "Check c/r of non-breaking leases";
const char *test_author = "Pavel Begunkov <asml.silence@gmail.com>";
char *filename;
TEST_OPTION(filename, string, "file name", 1);
char filename_rd[PATH_MAX];
char filename_wr[PATH_MAX];
static void close_files(int fd1, int fd2)
{
if (fd1 >= 0)
close(fd1);
if (fd2 >= 0)
close(fd2);
unlink(filename_rd);
unlink(filename_wr);
}
static int open_files(int *fd_rd, int *fd_wr)
{
*fd_rd = open(filename_rd, O_RDONLY | O_CREAT, 0666);
*fd_wr = open(filename_wr, O_WRONLY | O_CREAT, 0666);
if (*fd_rd < 0 || *fd_wr < 0) {
close_files(*fd_rd, *fd_wr);
return -1;
}
return 0;
}
static int check_lease_type(int fd, int expected_type)
{
int lease_type = fcntl(fd, F_GETLEASE);
if (lease_type != expected_type) {
if (lease_type < 0)
pr_perror("Can't acquire lease type\n");
else
pr_err("Mismatched lease type: %i\n", lease_type);
return -1;
}
return 0;
}
int main(int argc, char **argv)
{
int fd_rd = -1, fd_wr = -1;
test_init(argc, argv);
snprintf(filename_rd, sizeof(filename_rd), "%s.0", filename);
snprintf(filename_wr, sizeof(filename_wr), "%s.1", filename);
if (open_files(&fd_rd, &fd_wr)) {
pr_err("Can't open files\n");
return -1;
}
if (fcntl(fd_rd, F_SETLEASE, F_RDLCK) < 0 ||
fcntl(fd_wr, F_SETLEASE, F_WRLCK) < 0) {
pr_perror("Can't set leases\n");
close_files(fd_rd, fd_wr);
return -1;
}
test_daemon();
test_waitsig();
if (check_lease_type(fd_rd, F_RDLCK))
fail("Read lease check failed\n");
else if (check_lease_type(fd_wr, F_WRLCK))
fail("Write lease check failed\n");
else
pass();
close_files(fd_rd, fd_wr);
return 0;
}
{'feature': 'fdinfo_lock', 'opts': '--file-locks'}
#include <fcntl.h>
#include <stdio.h>
#include "zdtmtst.h"
#define FD_COUNT 3
#define FD_LEASED1 0
#define FD_LEASED2 2
#define FD_LEASE_FREE 1
const char *test_doc = "Check that extra leases are not set after c/r";
const char *test_author = "Pavel Begunkov <asml.silence@gmail.com>";
char *filename;
TEST_OPTION(filename, string, "file name", 1);
static void close_files(int fds[FD_COUNT])
{
int i;
for (i = 0; i < FD_COUNT; ++i)
if (fds[i] >= 0)
close(fds[i]);
unlink(filename);
}
static int open_files(int fds[FD_COUNT])
{
int i;
for (i = 0; i < FD_COUNT; ++i) {
fds[i] = open(filename, O_RDONLY | O_CREAT, 0666);
if (fds[i] < 0) {
close_files(fds);
return -1;
}
}
return 0;
}
static int check_lease_type(int fd, int expected_type)
{
int lease_type = fcntl(fd, F_GETLEASE);
if (lease_type != expected_type) {
if (lease_type < 0)
pr_perror("Can't acquire lease type\n");
else
pr_err("Mismatched lease type: %i\n", lease_type);
return -1;
}
return 0;
}
int main(int argc, char **argv)
{
int fds[FD_COUNT];
test_init(argc, argv);
if (open_files(fds)) {
pr_err("Can't open files\n");
return -1;
}
if (fcntl(fds[FD_LEASED1], F_SETLEASE, F_RDLCK) < 0 ||
fcntl(fds[FD_LEASED2], F_SETLEASE, F_RDLCK) < 0) {
pr_err("Can't set leases\n");
close_files(fds);
return -1;
}
test_daemon();
test_waitsig();
if (check_lease_type(fds[FD_LEASE_FREE], F_UNLCK))
fail("Unexpected lease was found (%i)\n", fds[FD_LEASE_FREE]);
else if (check_lease_type(fds[FD_LEASED1], F_RDLCK))
fail("Lease isn't set (%i)\n", fds[FD_LEASED1]);
else if (check_lease_type(fds[FD_LEASED2], F_RDLCK))
fail("Lease isn't set (%i)\n", fds[FD_LEASED2]);
else
pass();
close_files(fds);
return 0;
}
file_lease00.desc
\ No newline at end of file
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>
#include <limits.h>
#include "zdtmtst.h"
#define FD_COUNT 3
#define BREAK_SIGNUM SIGIO
const char *test_doc = "Check c/r of breaking leases";
const char *test_author = "Pavel Begunkov <asml.silence@gmail.com>";
char *filename;
TEST_OPTION(filename, string, "file name", 1);
char filename1[PATH_MAX];
char filename2[PATH_MAX];
char filename3[PATH_MAX];
int expected_fd;
int sigaction_error;
static void break_sigaction(int signo, siginfo_t *info, void *ctx)
{
if (signo != BREAK_SIGNUM) {
pr_err("Unexpected signal(%i)\n", signo);
sigaction_error = -1;
} else if (info->si_fd != expected_fd) {
pr_err("Unexpected fd(%i)\n", info->si_fd);
sigaction_error = -1;
}
expected_fd = -1;
}
static int check_lease_type(int fd, int expected_type)
{
int lease_type = fcntl(fd, F_GETLEASE);
if (lease_type != expected_type) {
if (lease_type < 0)
pr_perror("Can't acquire lease type\n");
else
pr_err("Mismatched lease type: %i\n", lease_type);
return -1;
}
return 0;
}
static int prepare_file(char *file, int file_type, int break_type)
{
int fd, fd_break;
int lease_type = (file_type == O_RDONLY) ? F_RDLCK : F_WRLCK;
fd = open(file, file_type | O_CREAT, 0666);
if (fd < 0) {
pr_perror("Can't open file (type %i)\n", file_type);
return fd;
}
if (fcntl(fd, F_SETLEASE, lease_type) < 0) {
pr_perror("Can't set exclusive lease\n");
goto err;
}
if (fcntl(fd, F_SETSIG, BREAK_SIGNUM) < 0) {
pr_perror("Can't set signum for file i/o\n");
goto err;
}
expected_fd = fd;
fd_break = open(file, break_type | O_NONBLOCK);
if (fd_break >= 0) {
close(fd_break);
pr_err("Conflicting lease not found\n");
goto err;
} else if (errno != EWOULDBLOCK) {
pr_perror("Can't break lease\n");
goto err;
}
return fd;
err:
close(fd);
return -1;
}
static void close_files(int fds[FD_COUNT])
{
int i;
for (i = 0; i < FD_COUNT; ++i)
if (fds[i] >= 0)
close(fds[i]);
unlink(filename1);
unlink(filename2);
unlink(filename3);
}
int main(int argc, char **argv)
{
int fds[FD_COUNT] = {};
int ret = -1;
struct sigaction act = {};
test_init(argc, argv);
snprintf(filename1, sizeof(filename1), "%s.0", filename);
snprintf(filename2, sizeof(filename2), "%s.1", filename);
snprintf(filename3, sizeof(filename3), "%s.2", filename);
act.sa_sigaction = break_sigaction;
act.sa_flags = SA_SIGINFO;
if (sigemptyset(&act.sa_mask) ||
sigaddset(&act.sa_mask, BREAK_SIGNUM) ||
sigaction(BREAK_SIGNUM, &act, NULL)) {
pr_perror("Can't set signal action\n");
fail();
return -1;
}
sigaction_error = 0;
fds[0] = prepare_file(filename1, O_RDONLY, O_WRONLY);
fds[1] = prepare_file(filename2, O_WRONLY, O_RDONLY);
fds[2] = prepare_file(filename3, O_WRONLY, O_WRONLY);
if (fds[0] < 0 || fds[1] < 0 || fds[2] < 0 || sigaction_error)
goto done;
test_daemon();
test_waitsig();
ret = 0;
if (sigaction_error)
fail("Ghost signal\n");
else if (check_lease_type(fds[0], F_UNLCK) ||
check_lease_type(fds[1], F_RDLCK) ||
check_lease_type(fds[2], F_UNLCK))
fail("Lease type doesn't match\n");
else
pass();
done:
close_files(fds);
return ret;
}
file_lease00.desc
\ No newline at end of file
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>
#include <limits.h>
#include <sys/wait.h>
#include "zdtmtst.h"
#define BREAK_SIGNUM SIGIO
const char *test_doc = "Check multiple fds on OFD with breaking leases";
const char *test_author = "Pavel Begunkov <asml.silence@gmail.com>";
char *filename;
TEST_OPTION(filename, string, "file name", 1);
int expected_fd;
int sigaction_error;
static void break_sigaction(int signo, siginfo_t *info, void *ctx)
{
if (signo != BREAK_SIGNUM) {
pr_err("Unexpected signal(%i)\n", signo);
sigaction_error = -1;
} else if (info->si_fd != expected_fd) {
pr_err("Unexpected fd(%i)\n", info->si_fd);
sigaction_error = -1;
}
expected_fd = -1;
}
static int check_lease_type(int fd, int expected_type)
{
int lease_type = fcntl(fd, F_GETLEASE);
if (lease_type != expected_type) {
if (lease_type < 0)
pr_perror("Can't acquire lease type\n");
else
pr_err("Mismatched lease type: %i\n", lease_type);
return -1;
}
return 0;
}
static int prepare_file(char *file, int file_type, int break_type)
{
int fd, fd_break;
int lease_type = (file_type == O_RDONLY) ? F_RDLCK : F_WRLCK;
fd = open(file, file_type | O_CREAT, 0666);
if (fd < 0) {
pr_perror("Can't open file (type %i)\n", file_type);
return fd;
}
if (fcntl(fd, F_SETLEASE, lease_type) < 0) {
pr_perror("Can't set exclusive lease\n");
goto err;
}
if (fcntl(fd, F_SETSIG, BREAK_SIGNUM) < 0) {
pr_perror("Can't set signum for file i/o\n");
goto err;
}
expected_fd = fd;
fd_break = open(file, break_type | O_NONBLOCK);
if (fd_break >= 0) {
close(fd_break);
pr_err("Conflicting lease not found\n");
goto err;
} else if (errno != EWOULDBLOCK) {
pr_perror("Can't break lease\n");
goto err;
}
return fd;
err:
close(fd);
return -1;
}
int main(int argc, char **argv)
{
int fd = -1, fd_dup = -1;
int ret = -1;
struct sigaction act = {};
int pid;
test_init(argc, argv);
act.sa_sigaction = break_sigaction;
act.sa_flags = SA_SIGINFO;
if (sigemptyset(&act.sa_mask) ||
sigaddset(&act.sa_mask, BREAK_SIGNUM) ||
sigaction(BREAK_SIGNUM, &act, NULL)) {
pr_perror("Can't set signal action\n");
return -1;
}
sigaction_error = 0;
fd = prepare_file(filename, O_RDWR, O_WRONLY);
if (fd < 0 || sigaction_error)
goto done;
pid = fork();
if (pid < 0)
return 1;
if (pid == 0) {
test_waitsig();
if (check_lease_type(fd, F_UNLCK))
return 1;
close(fd);
return 0;
}
ret = fd_dup = dup(fd);
if (fd_dup < 0) {
pr_perror("Can't dup fd\n");
goto done;
}
ret = 0;
test_daemon();
test_waitsig();
kill(pid, SIGTERM);
waitpid(pid, NULL, 0);
if (sigaction_error)
fail("Ghost signal\n");
else if (check_lease_type(fd, F_UNLCK))
fail("Lease type doesn't match\n");
else
pass();
done:
if (fd >= 0)
close(fd);
if (fd_dup >= 0)
close(fd_dup);
unlink(filename);
return ret;
}
file_lease00.desc
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment