2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-31 14:25:49 +00:00
Files
criu/test/zdtm/static/file_lease03.c
Adrian Reber 93dd984ca0 Run 'make indent' on all C files
Acked-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
2021-09-03 10:31:00 -07:00

144 lines
2.8 KiB
C

#include <fcntl.h>
#include <stdio.h>
#include <signal.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");
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)", file_type);
return fd;
}
if (fcntl(fd, F_SETLEASE, lease_type) < 0) {
pr_perror("Can't set exclusive lease");
goto err;
}
if (fcntl(fd, F_SETSIG, BREAK_SIGNUM) < 0) {
pr_perror("Can't set signum for file i/o");
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");
goto err;
}
return fd;
err:
close(fd);
return -1;
}
int main(int argc, char **argv)
{
int fd = -1, fd_dup = -1;
int status, ret = -1;
struct sigaction act = {};
pid_t 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");
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");
goto done;
}
ret = 0;
test_daemon();
test_waitsig();
kill(pid, SIGTERM);
ret = waitpid(pid, &status, 0);
if (ret < 0 || !WIFEXITED(status) || WEXITSTATUS(status))
fail();
if (sigaction_error)
fail("Ghost signal");
else if (check_lease_type(fd, F_UNLCK))
fail("Lease type doesn't match");
else
pass();
done:
if (fd >= 0)
close(fd);
if (fd_dup >= 0)
close(fd_dup);
unlink(filename);
return ret;
}