Commit a52a66f6 authored by Qiang Huang's avatar Qiang Huang Committed by Pavel Emelyanov

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: 's avatarQiang Huang <h.huangqiang@huawei.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 882005a0
......@@ -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 = \
......
#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;
}
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