[CRIU] [PATCH v5 4/4] zdtm: Add file lease tests

Pavel Begunkov asml.silence at gmail.com
Mon Oct 2 23:48:20 MSK 2017


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: Pavel Begunkov <asml.silence at gmail.com>
---
 test/zdtm/static/Makefile          |   4 +
 test/zdtm/static/file_lease00.c    |  84 +++++++++++++++++++++
 test/zdtm/static/file_lease00.desc |   1 +
 test/zdtm/static/file_lease01.c    |  88 ++++++++++++++++++++++
 test/zdtm/static/file_lease01.desc |   1 +
 test/zdtm/static/file_lease02.c    | 145 +++++++++++++++++++++++++++++++++++++
 test/zdtm/static/file_lease02.desc |   1 +
 test/zdtm/static/file_lease03.c    | 145 +++++++++++++++++++++++++++++++++++++
 test/zdtm/static/file_lease03.desc |   1 +
 9 files changed, 470 insertions(+)
 create mode 100644 test/zdtm/static/file_lease00.c
 create mode 100644 test/zdtm/static/file_lease00.desc
 create mode 100644 test/zdtm/static/file_lease01.c
 create mode 120000 test/zdtm/static/file_lease01.desc
 create mode 100644 test/zdtm/static/file_lease02.c
 create mode 120000 test/zdtm/static/file_lease02.desc
 create mode 100644 test/zdtm/static/file_lease03.c
 create mode 120000 test/zdtm/static/file_lease03.desc

diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
index 2c6353ee..5a4a9c27 100644
--- a/test/zdtm/static/Makefile
+++ b/test/zdtm/static/Makefile
@@ -233,6 +233,10 @@ TST_FILE	=				\
 		sockets00			\
 		sockets03			\
 		sockets_dgram			\
+		file_lease00			\
+		file_lease01			\
+		file_lease02			\
+		file_lease03			\
 		file_locks00			\
 		file_locks01			\
 		file_locks02			\
diff --git a/test/zdtm/static/file_lease00.c b/test/zdtm/static/file_lease00.c
new file mode 100644
index 00000000..8413f831
--- /dev/null
+++ b/test/zdtm/static/file_lease00.c
@@ -0,0 +1,84 @@
+#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 at 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;
+}
diff --git a/test/zdtm/static/file_lease00.desc b/test/zdtm/static/file_lease00.desc
new file mode 100644
index 00000000..f394d033
--- /dev/null
+++ b/test/zdtm/static/file_lease00.desc
@@ -0,0 +1 @@
+{'feature': 'fdinfo_lock', 'opts': '--file-locks'}
diff --git a/test/zdtm/static/file_lease01.c b/test/zdtm/static/file_lease01.c
new file mode 100644
index 00000000..90fa74a1
--- /dev/null
+++ b/test/zdtm/static/file_lease01.c
@@ -0,0 +1,88 @@
+#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 at 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;
+}
+
diff --git a/test/zdtm/static/file_lease01.desc b/test/zdtm/static/file_lease01.desc
new file mode 120000
index 00000000..fba66d32
--- /dev/null
+++ b/test/zdtm/static/file_lease01.desc
@@ -0,0 +1 @@
+file_lease00.desc
\ No newline at end of file
diff --git a/test/zdtm/static/file_lease02.c b/test/zdtm/static/file_lease02.c
new file mode 100644
index 00000000..cd7945d3
--- /dev/null
+++ b/test/zdtm/static/file_lease02.c
@@ -0,0 +1,145 @@
+#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 at 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;
+}
+
diff --git a/test/zdtm/static/file_lease02.desc b/test/zdtm/static/file_lease02.desc
new file mode 120000
index 00000000..fba66d32
--- /dev/null
+++ b/test/zdtm/static/file_lease02.desc
@@ -0,0 +1 @@
+file_lease00.desc
\ No newline at end of file
diff --git a/test/zdtm/static/file_lease03.c b/test/zdtm/static/file_lease03.c
new file mode 100644
index 00000000..fcdcce13
--- /dev/null
+++ b/test/zdtm/static/file_lease03.c
@@ -0,0 +1,145 @@
+#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 at 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;
+}
+
diff --git a/test/zdtm/static/file_lease03.desc b/test/zdtm/static/file_lease03.desc
new file mode 120000
index 00000000..fba66d32
--- /dev/null
+++ b/test/zdtm/static/file_lease03.desc
@@ -0,0 +1 @@
+file_lease00.desc
\ No newline at end of file
-- 
2.14.1.473.g3ec7d702a8



More information about the CRIU mailing list