mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-30 22:05:36 +00:00
zdtm: add posix file lock's test case
We check read lock and write lock for posix file locks. After restore, we use fcntl(fd, F_GETLK, &lock), to see if the file is hold the same lock as it was dumped. Signed-off-by: Qiang Huang <h.huangqiang@huawei.com> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
committed by
Pavel Emelyanov
parent
882005a0ed
commit
a52a66f652
11
test/zdtm.sh
11
test/zdtm.sh
@@ -119,6 +119,10 @@ static/sem
|
||||
transition/ipc
|
||||
"
|
||||
|
||||
FILE_LOCK_TEST_LIST="
|
||||
static/file_locks00
|
||||
"
|
||||
|
||||
TEST_CR_KERNEL="
|
||||
static/sock_opts01
|
||||
static/sockets01
|
||||
@@ -442,8 +446,11 @@ if [ $# -eq 0 ]; then
|
||||
for t in $IPC_TEST_LIST; do
|
||||
run_test $t -n ipc || case_error $t
|
||||
done
|
||||
for t in $FILE_LOCK_TEST_LIST; do
|
||||
run_test $t -l || case_error $t
|
||||
done
|
||||
elif [ "$1" = "-l" ]; then
|
||||
echo $TEST_LIST $UTS_TEST_LIST $MNT_TEST_LIST $IPC_TEST_LIST | tr ' ' '\n'
|
||||
echo $TEST_LIST $UTS_TEST_LIST $MNT_TEST_LIST $IPC_TEST_LIST $FILE_LOCK_TEST_LIST | tr ' ' '\n'
|
||||
elif [ "$1" = "-h" ]; then
|
||||
cat >&2 <<EOF
|
||||
This script is used for executing unit tests.
|
||||
@@ -465,6 +472,8 @@ else
|
||||
run_test $1 -n mnt || case_error $1
|
||||
elif echo $IPC_TEST_LIST | fgrep -qw $1; then
|
||||
run_test $1 -n ipc || case_error $1
|
||||
elif echo $FILE_LOCK_TEST_LIST | fgrep -qw $1; then
|
||||
run_test $1 -l || case_error $1
|
||||
else
|
||||
run_test $1 || case_error $1
|
||||
fi
|
||||
|
@@ -85,6 +85,7 @@ TST_NOFILE = \
|
||||
cow00 \
|
||||
child_opened_proc \
|
||||
posix_timers \
|
||||
file_locks00 \
|
||||
# jobctl00 \
|
||||
|
||||
TST_FILE = \
|
||||
|
179
test/zdtm/live/static/file_locks00.c
Normal file
179
test/zdtm/live/static/file_locks00.c
Normal file
@@ -0,0 +1,179 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/wait.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zdtmtst.h"
|
||||
|
||||
const char *test_doc = "Check that posix flocks are restored";
|
||||
const char *test_author = "Qiang Huang <h.huangqiang@huawei.com>";
|
||||
|
||||
char file0[] = "/tmp/zdtm_file_locks_XXXXXX";
|
||||
char file1[] = "/tmp/zdtm_file_locks_XXXXXX";
|
||||
|
||||
static int lock_reg(int fd, int cmd, int type, int whence,
|
||||
off_t offset, off_t len)
|
||||
{
|
||||
struct flock lock;
|
||||
|
||||
lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */
|
||||
lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
|
||||
lock.l_start = offset; /* byte offset, relative to l_whence */
|
||||
lock.l_len = len; /* #bytes (0 means to EOF) */
|
||||
|
||||
return fcntl(fd, cmd, &lock);
|
||||
}
|
||||
|
||||
#define set_read_lock(fd, whence, offset, len) \
|
||||
lock_reg(fd, F_SETLK, F_RDLCK, whence, offset, len)
|
||||
#define set_write_lock(fd, whence, offset, len) \
|
||||
lock_reg(fd, F_SETLK, F_WRLCK, whence, offset, len)
|
||||
|
||||
static int check_read_lock(int fd, int whence, off_t offset, off_t len)
|
||||
{
|
||||
struct flock lock;
|
||||
int ret;
|
||||
|
||||
lock.l_type = F_RDLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */
|
||||
lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
|
||||
lock.l_start = offset; /* byte offset, relative to l_whence */
|
||||
lock.l_len = len; /* #bytes (0 means to EOF) */
|
||||
lock.l_pid = -1;
|
||||
|
||||
ret = fcntl(fd, F_GETLK, &lock);
|
||||
if (ret == -1) {
|
||||
err("F_GETLK failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lock.l_pid == -1) {
|
||||
/* Share lock should succeed. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
fail("Read lock check failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int check_write_lock(int fd, int whence, off_t offset, off_t len)
|
||||
{
|
||||
struct flock lock;
|
||||
|
||||
int ret;
|
||||
pid_t ppid = getppid();
|
||||
|
||||
lock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */
|
||||
lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
|
||||
lock.l_start = offset; /* byte offset, relative to l_whence */
|
||||
lock.l_len = len; /* #bytes (0 means to EOF) */
|
||||
lock.l_pid = -1;
|
||||
|
||||
ret = fcntl(fd, F_GETLK, &lock);
|
||||
if (ret == -1) {
|
||||
err("F_GETLK failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lock.l_pid == -1) {
|
||||
fail("Write lock check failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* It only succeed when the file lock's owner is exactly
|
||||
* the same as the file lock was dumped.
|
||||
*/
|
||||
if (lock.l_pid == ppid)
|
||||
return 0;
|
||||
|
||||
fail("Write lock check failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int check_file_locks()
|
||||
{
|
||||
int fd_0, fd_1;
|
||||
int ret0, ret1;
|
||||
|
||||
fd_0 = open(file0, O_RDWR | O_CREAT, 0644);
|
||||
if (fd_0 < 0) {
|
||||
err("Unable to open file %s", file0);
|
||||
return -1;
|
||||
}
|
||||
ret0 = check_read_lock(fd_0, SEEK_SET, 0, 0);
|
||||
|
||||
fd_1 = open(file1, O_RDWR | O_CREAT, 0644);
|
||||
if (fd_1 < 0) {
|
||||
close(fd_0);
|
||||
unlink(file0);
|
||||
err("Unable to open file %s", file1);
|
||||
return -1;
|
||||
}
|
||||
ret1 = check_write_lock(fd_1, SEEK_SET, 0, 0);
|
||||
|
||||
close(fd_0);
|
||||
close(fd_1);
|
||||
|
||||
return ret0 | ret1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd_0, fd_1;
|
||||
pid_t pid;
|
||||
|
||||
test_init(argc, argv);
|
||||
|
||||
fd_0 = mkstemp(file0);
|
||||
if (fd_0 < 0) {
|
||||
err("Unable to open file %s", file0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd_1 = mkstemp(file1);
|
||||
if (fd_1 < 0) {
|
||||
close(fd_0);
|
||||
unlink(file0);
|
||||
err("Unable to open file %s", file1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
err("Can't fork: %m\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pid == 0) { /* child will check father's file locks */
|
||||
test_waitsig();
|
||||
|
||||
if (check_file_locks()) {
|
||||
fail("Posix file lock check failed");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pass();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
set_read_lock(fd_0, SEEK_SET, 0, 0);
|
||||
set_write_lock(fd_1, SEEK_SET, 0, 0);
|
||||
|
||||
test_daemon();
|
||||
test_waitsig();
|
||||
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
close(fd_0);
|
||||
close(fd_1);
|
||||
unlink(file0);
|
||||
unlink(file1);
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user