[CRIU] [PATCH 2/2] zdtm: Add OFD file locks test

Eugene Batalov eabatalov89 at gmail.com
Fri Dec 30 03:46:27 PST 2016


Pavel,

OFD locks are quite new and were added to Linux in 2014. What if they are
not supported on host that runs zdtm tests? Should we add OFD locks support
checks into the tests? If yes then where it is better to put them?
Look here:
https://ci.openvz.org/job/CRIU/job/CRIU-virtuozzo/job/criu-dev/1244/tapResults/
It looks like OFD locks are really not supported on testing host.


2016-12-30 14:11 GMT+03:00 Eugene Batalov <eabatalov89 at gmail.com>:

> Thank you, Pavel.
>
> 2016-12-30 13:47 GMT+03:00 Pavel Emelyanov <xemul at virtuozzo.com>:
>
>> On 12/30/2016 12:17 PM, Pavel Emelyanov wrote:
>> > On 12/20/2016 01:24 PM, Pavel Begunkov wrote:
>> >> From: Begunkov Pavel <asml.silence at gmail.com>
>> >>
>> >> There are 3 tests that cover the following cases:
>> >>
>> >> 1. single OFD lock
>> >> 2. overlapped OFD locks
>> >> 3. inhertited OFD locks
>> >>
>> >> Tests logic is similar to logic of tests for other lock types.
>> >>
>> >> OFD lock specific header-only library was added to avoid code
>> >> duplication in the tests.
>> >>
>> >> Signed-off-by: Begunkov Pavel <asml.silence at gmail.com>
>> >> Signed-off-by: Eugene Batalov <eabatalov89 at gmail.com>
>> >> ---
>> >>  test/zdtm/static/Makefile          |   3 +
>> >>  test/zdtm/static/file_locks06.c    |  67 ++++++++++++++++
>> >>  test/zdtm/static/file_locks06.desc |   1 +
>> >>  test/zdtm/static/file_locks07.c    | 101 ++++++++++++++++++++++++
>> >>  test/zdtm/static/file_locks07.desc |   1 +
>> >>  test/zdtm/static/file_locks08.c    |  86 +++++++++++++++++++++
>> >
>> > Guys, this test fails:
>>
>> I've fixed it with 7d38db56a67d5f0d9f6e3fb499197b4d081108b2
>>
>> > # ./zdtm.py run -t zdtm/static/file_locks08
>> > cc -D_GNU_SOURCE    umount2.c   -o umount2
>> > cc -D_GNU_SOURCE    zdtm_ct.c   -o zdtm_ct
>> > === Run 1/1 ================ zdtm/static/file_locks08
>> >
>> > ====================== Run zdtm/static/file_locks08 in h
>> =======================
>> > cc -g -O2 -Wall -Werror -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0  -iquote
>> ../lib/arch/x86/include -I../lib   file_locks08.c ../lib/libzdtmtst.a
>> ../lib/libzdtmtst.a -o file_locks08
>> > Start test
>> > ./file_locks08 --pidfile=file_locks08.pid --outfile=file_locks08.out
>> --filename=file_locks08.test
>> > Run criu dump
>> > Run criu restore
>> > Send the 15 signal to  39
>> > Wait for zdtm/static/file_locks08(39) to die for 0.100000
>> > Removing dump/zdtm/static/file_locks08/39
>> > ====================== Test zdtm/static/file_locks08 PASS
>> ======================
>> >
>> > ====================== Run zdtm/static/file_locks08 in ns
>> ======================
>> > Construct root for zdtm/static/file_locks08
>> > Start test
>> > ./file_locks08 --pidfile=file_locks08.pid --outfile=file_locks08.out
>> --filename=file_locks08.test
>> > Run criu dump
>> > Run criu restore
>> > 5: Old files lost: set(['1', '0', '3', '2', '4'])
>> > 5: New files appeared: set([])
>> > ############## Test zdtm/static/file_locks08 FAIL at fds compare
>> ###############
>> > Send the 9 signal to  100
>> > ##################################### FAIL
>> #####################################
>> >
>> > -- Pavel
>> >
>> >>  test/zdtm/static/file_locks08.desc |   1 +
>> >>  test/zdtm/static/ofd_file_locks.h  | 153
>> +++++++++++++++++++++++++++++++++++++
>> >>  8 files changed, 413 insertions(+)
>> >>  create mode 100644 test/zdtm/static/file_locks06.c
>> >>  create mode 100644 test/zdtm/static/file_locks06.desc
>> >>  create mode 100644 test/zdtm/static/file_locks07.c
>> >>  create mode 100644 test/zdtm/static/file_locks07.desc
>> >>  create mode 100644 test/zdtm/static/file_locks08.c
>> >>  create mode 100644 test/zdtm/static/file_locks08.desc
>> >>  create mode 100644 test/zdtm/static/ofd_file_locks.h
>> >>
>> >> diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
>> >> index c932093..f270f9f 100644
>> >> --- a/test/zdtm/static/Makefile
>> >> +++ b/test/zdtm/static/Makefile
>> >> @@ -221,6 +221,9 @@ TST_FILE =                               \
>> >>              file_locks03                    \
>> >>              file_locks04                    \
>> >>              file_locks05                    \
>> >> +            file_locks06                    \
>> >> +            file_locks07                    \
>> >> +            file_locks08                    \
>> >>              netns-nf                        \
>> >>              maps_file_prot                  \
>> >>              socket_close_data01             \
>> >> diff --git a/test/zdtm/static/file_locks06.c
>> b/test/zdtm/static/file_locks06.c
>> >> new file mode 100644
>> >> index 0000000..2e1ba43
>> >> --- /dev/null
>> >> +++ b/test/zdtm/static/file_locks06.c
>> >> @@ -0,0 +1,67 @@
>> >> +#define _GNU_SOURCE
>> >> +
>> >> +#include <sys/file.h>
>> >> +#include <unistd.h>
>> >> +#include <fcntl.h>
>> >> +
>> >> +#include "ofd_file_locks.h"
>> >> +#include "zdtmtst.h"
>> >> +
>> >> +const char *test_doc    = "Check that OFD lock for the whole file is
>> restored";
>> >> +const char *test_author = "Begunkov Pavel <asml.silence at gmail.com>";
>> >> +
>> >> +char *filename;
>> >> +TEST_OPTION(filename, string, "file name", 1);
>> >> +
>> >> +
>> >> +int init_lock(int *fd, struct flock *lck)
>> >> +{
>> >> +    *fd = open(filename, O_RDWR | O_CREAT, 0666);
>> >> +    if (*fd < 0) {
>> >> +            pr_perror("Can't open file");
>> >> +            return -1;
>> >> +    }
>> >> +
>> >> +    lck->l_type = F_WRLCK;
>> >> +    lck->l_whence = SEEK_SET;
>> >> +    lck->l_start = 0;
>> >> +    lck->l_len = 0;
>> >> +    lck->l_pid = 0;
>> >> +
>> >> +    if (fcntl(*fd, F_OFD_SETLK, lck) < 0) {
>> >> +            pr_perror("Can't set ofd lock");
>> >> +            return -1;
>> >> +    }
>> >> +    return 0;
>> >> +}
>> >> +
>> >> +void cleanup(int *fd)
>> >> +{
>> >> +    if (close(*fd))
>> >> +            pr_perror("Can't close fd\n");
>> >> +
>> >> +    if (unlink(filename))
>> >> +            pr_perror("Can't unlink file\n");
>> >> +}
>> >> +
>> >> +int main(int argc, char **argv)
>> >> +{
>> >> +    int fd;
>> >> +    struct flock lck;
>> >> +
>> >> +    test_init(argc, argv);
>> >> +    if (init_lock(&fd, &lck))
>> >> +            return 1;
>> >> +
>> >> +    test_daemon();
>> >> +    test_waitsig();
>> >> +
>> >> +    if (check_file_lock_restored(getpid(), fd, &lck) ||
>> >> +            check_lock_exists(filename, &lck) < 0)
>> >> +            fail("OFD file locks check failed\n");
>> >> +    else
>> >> +            pass();
>> >> +
>> >> +    cleanup(&fd);
>> >> +    return 0;
>> >> +}
>> >> diff --git a/test/zdtm/static/file_locks06.desc
>> b/test/zdtm/static/file_locks06.desc
>> >> new file mode 100644
>> >> index 0000000..80cd04e
>> >> --- /dev/null
>> >> +++ b/test/zdtm/static/file_locks06.desc
>> >> @@ -0,0 +1 @@
>> >> +{'flags': 'excl', 'opts': '--file-locks'}
>> >> diff --git a/test/zdtm/static/file_locks07.c
>> b/test/zdtm/static/file_locks07.c
>> >> new file mode 100644
>> >> index 0000000..1f94625
>> >> --- /dev/null
>> >> +++ b/test/zdtm/static/file_locks07.c
>> >> @@ -0,0 +1,101 @@
>> >> +#define _GNU_SOURCE
>> >> +
>> >> +#include <sys/file.h>
>> >> +#include <unistd.h>
>> >> +#include <fcntl.h>
>> >> +
>> >> +#include "ofd_file_locks.h"
>> >> +#include "zdtmtst.h"
>> >> +
>> >> +const char *test_doc    = "Check that 'overlapping' OFD read locks
>> work";
>> >> +const char *test_author = "Begunkov Pavel <asml.silence at gmail.com>";
>> >> +
>> >> +char *filename;
>> >> +TEST_OPTION(filename, string, "file name", 1);
>> >> +
>> >> +
>> >> +#define FILE_NUM 4
>> >> +static int fds[FILE_NUM];
>> >> +static struct flock lcks[FILE_NUM];
>> >> +static short types[] = {F_RDLCK, F_RDLCK, F_RDLCK, F_RDLCK};
>> >> +static off_t starts[] = {0, 10, 0, 70};
>> >> +static off_t lens[]  = {20, 30, 100, 200};
>> >> +
>> >> +void fill_lock(struct flock *lock, off_t start, off_t len, short int
>> type)
>> >> +{
>> >> +    lock->l_start = start;
>> >> +    lock->l_len = len;
>> >> +    lock->l_type = type;
>> >> +    lock->l_whence = SEEK_SET;
>> >> +    lock->l_pid = 0;
>> >> +}
>> >> +
>> >> +int init_file_locks(void)
>> >> +{
>> >> +    size_t i;
>> >> +
>> >> +    for (i = 0; i < FILE_NUM; ++i)
>> >> +            fill_lock(&lcks[i], starts[i], lens[i], types[i]);
>> >> +
>> >> +    for (i = 0; i < FILE_NUM; ++i) {
>> >> +            fds[i] = open(filename, O_RDWR | O_CREAT, 0666);
>> >> +
>> >> +            if (fds[i] < 0) {
>> >> +                    pr_perror("Can't open file");
>> >> +                    return -1;
>> >> +            }
>> >> +    }
>> >> +
>> >> +    for (i = 0; i < FILE_NUM; ++i)
>> >> +            if (fcntl(fds[i], F_OFD_SETLKW, &lcks[i]) < 0) {
>> >> +                    pr_perror("Can't set ofd lock");
>> >> +                    return -1;
>> >> +            }
>> >> +
>> >> +    return 0;
>> >> +}
>> >> +
>> >> +void cleanup(void)
>> >> +{
>> >> +    size_t i;
>> >> +
>> >> +    for (i = 0; i < FILE_NUM; ++i)
>> >> +            if (close(fds[i]))
>> >> +                    pr_perror("Can't close fd\n");
>> >> +
>> >> +    if (unlink(filename))
>> >> +            pr_perror("Can't unlink file failed\n");
>> >> +}
>> >> +
>> >> +int check_file_locks_restored(void)
>> >> +{
>> >> +    size_t i;
>> >> +    int pid = getpid();
>> >> +
>> >> +    for (i = 0; i < FILE_NUM; ++i) {
>> >> +            if (check_file_lock_restored(pid, fds[i], &lcks[i]))
>> >> +                    return -1;
>> >> +            if (check_lock_exists(filename, &lcks[i]) < 0)
>> >> +                    return -1;
>> >> +    }
>> >> +
>> >> +    return 0;
>> >> +}
>> >> +
>> >> +int main(int argc, char **argv)
>> >> +{
>> >> +    test_init(argc, argv);
>> >> +    if (init_file_locks())
>> >> +            return -1;
>> >> +
>> >> +    test_daemon();
>> >> +    test_waitsig();
>> >> +
>> >> +    if (check_file_locks_restored())
>> >> +            fail("OFD file locks check failed\n");
>> >> +    else
>> >> +            pass();
>> >> +
>> >> +    cleanup();
>> >> +    return 0;
>> >> +}
>> >> diff --git a/test/zdtm/static/file_locks07.desc
>> b/test/zdtm/static/file_locks07.desc
>> >> new file mode 100644
>> >> index 0000000..80cd04e
>> >> --- /dev/null
>> >> +++ b/test/zdtm/static/file_locks07.desc
>> >> @@ -0,0 +1 @@
>> >> +{'flags': 'excl', 'opts': '--file-locks'}
>> >> diff --git a/test/zdtm/static/file_locks08.c
>> b/test/zdtm/static/file_locks08.c
>> >> new file mode 100644
>> >> index 0000000..a0d93dd
>> >> --- /dev/null
>> >> +++ b/test/zdtm/static/file_locks08.c
>> >> @@ -0,0 +1,86 @@
>> >> +#define _GNU_SOURCE
>> >> +
>> >> +#include <sys/wait.h>
>> >> +#include <sys/file.h>
>> >> +#include <unistd.h>
>> >> +#include <fcntl.h>
>> >> +#include <stdlib.h>
>> >> +
>> >> +#include "ofd_file_locks.h"
>> >> +#include "zdtmtst.h"
>> >> +
>> >> +const char *test_doc    = "Check that inherited OFD locks work";
>> >> +const char *test_author = "Begunkov Pavel <asml.silence at gmail.com>";
>> >> +
>> >> +char *filename;
>> >> +TEST_OPTION(filename, string, "file name", 1);
>> >> +
>> >> +
>> >> +int init_file_lock(int *fd, struct flock *lck)
>> >> +{
>> >> +    *fd = open(filename, O_RDWR | O_CREAT, 0666);
>> >> +    if (*fd < 0) {
>> >> +            pr_perror("Can't open file");
>> >> +            return -1;
>> >> +    }
>> >> +
>> >> +    lck->l_type = F_WRLCK;
>> >> +    lck->l_whence = SEEK_SET;
>> >> +    lck->l_start = 0;
>> >> +    lck->l_len = 0; /* lock whole file */
>> >> +    lck->l_pid = 0; /* should be 0 for ofd lock */
>> >> +
>> >> +    if (fcntl(*fd, F_OFD_SETLKW, lck) < 0) {
>> >> +            pr_perror("Can't set ofd lock");
>> >> +            return -1;
>> >> +    }
>> >> +    return 0;
>> >> +}
>> >> +
>> >> +void cleanup(int *fd)
>> >> +{
>> >> +    if (close(*fd))
>> >> +            pr_perror("Can't close fd\n");
>> >> +
>> >> +    if (unlink(filename))
>> >> +            pr_perror("Can't unlink file\n");
>> >> +}
>> >> +
>> >> +int main(int argc, char **argv)
>> >> +{
>> >> +    int fd;
>> >> +    int pid;
>> >> +    int status;
>> >> +    int ret = 0;
>> >> +    struct flock lck;
>> >> +
>> >> +    test_init(argc, argv);
>> >> +    if (init_file_lock(&fd, &lck))
>> >> +            return -1;
>> >> +
>> >> +    pid = fork();
>> >> +    if (pid == 0) {
>> >> +            if (check_file_lock_restored(getpid(), fd, &lck) ||
>> >> +                    check_lock_exists(filename, &lck) < 0)
>> >> +                    ret = -1;
>> >> +            exit(ret);
>> >> +    }
>> >> +
>> >> +    test_daemon();
>> >> +    test_waitsig();
>> >> +
>> >> +    if (check_file_lock_restored(getpid(), fd, &lck) ||
>> >> +            check_lock_exists(filename, &lck) < 0)
>> >> +            fail("OFD file locks check failed\n");
>> >> +
>> >> +    kill(pid, SIGTERM);
>> >> +    ret = waitpid(pid, &status, 0);
>> >> +
>> >> +    if (ret < 0 || !WIFEXITED(status) || WEXITSTATUS(status))
>> >> +            fail("OFD file locks check failed\n");
>> >> +    else
>> >> +            pass();
>> >> +
>> >> +    cleanup(&fd);
>> >> +    return 0;
>> >> +}
>> >> diff --git a/test/zdtm/static/file_locks08.desc
>> b/test/zdtm/static/file_locks08.desc
>> >> new file mode 100644
>> >> index 0000000..80cd04e
>> >> --- /dev/null
>> >> +++ b/test/zdtm/static/file_locks08.desc
>> >> @@ -0,0 +1 @@
>> >> +{'flags': 'excl', 'opts': '--file-locks'}
>> >> diff --git a/test/zdtm/static/ofd_file_locks.h
>> b/test/zdtm/static/ofd_file_locks.h
>> >> new file mode 100644
>> >> index 0000000..049401a
>> >> --- /dev/null
>> >> +++ b/test/zdtm/static/ofd_file_locks.h
>> >> @@ -0,0 +1,153 @@
>> >> +#ifndef ZDTM_OFD_FILE_LOCKS_H_
>> >> +#define ZDTM_OFD_FILE_LOCKS_H_
>> >> +
>> >> +#include <sys/file.h>
>> >> +#include <unistd.h>
>> >> +#include <fcntl.h>
>> >> +#include <string.h>
>> >> +
>> >> +#include "zdtmtst.h"
>> >> +#include "fs.h"
>> >> +
>> >> +#ifndef F_OFD_GETLK
>> >> +#define F_OFD_GETLK 36
>> >> +#define F_OFD_SETLK 37
>> >> +#define F_OFD_SETLKW        38
>> >> +#endif
>> >> +
>> >> +/*
>> >> + * Header library for parsing of OFD locks
>> >> + * from procfs and checking them after restoring.
>> >> + */
>> >> +
>> >> +static int parse_ofd_lock(char *buf, struct flock *lck)
>> >> +{
>> >> +    char fl_flag[10], fl_type[15], fl_option[10], fl_end[32];
>> >> +    long long start;
>> >> +    int num;
>> >> +
>> >> +    if (strncmp(buf, "lock:\t", 6) != 0)
>> >> +            return 1; /* isn't lock, skip record */
>> >> +
>> >> +    num = sscanf(buf,
>> >> +            "%*s %*d: %s %s %s %*d %*x:%*x:%*d %lld %s",
>> >> +            fl_flag, fl_type, fl_option, &start, fl_end);
>> >> +
>> >> +    if (num < 4) {
>> >> +            pr_err("Invalid lock info %s\n", buf);
>> >> +            return -1;
>> >> +    }
>> >> +    if (strcmp(fl_flag, "OFDLCK"))
>> >> +            return 1;
>> >> +
>> >> +    lck->l_start = start;
>> >> +
>> >> +    if (strcmp(fl_end, "EOF")) {
>> >> +            unsigned long end;
>> >> +
>> >> +            if (sscanf(fl_end, "%lu", &end) <= 0) {
>> >> +                    pr_err("Invalid lock entry\n");
>> >> +                    return -1;
>> >> +            }
>> >> +            lck->l_len = end - lck->l_start + 1;
>> >> +    } else {
>> >> +            lck->l_len = 0;
>> >> +    }
>> >> +    if (strcmp(fl_option, "WRITE") == 0)
>> >> +            lck->l_type = F_WRLCK;
>> >> +    else
>> >> +            lck->l_type = F_RDLCK;
>> >> +
>> >> +    return 0;
>> >> +}
>> >> +
>> >> +static int read_fd_ofd_lock(int pid, int fd, struct flock *lck)
>> >> +{
>> >> +    char path[PATH_MAX];
>> >> +    char buf[100];
>> >> +    int num;
>> >> +    FILE *proc_file = NULL;
>> >> +
>> >> +    sprintf(path, "/proc/%i/fdinfo/%i", pid, fd);
>> >> +    proc_file = fopen(path, "r");
>> >> +
>> >> +    if (!proc_file) {
>> >> +            pr_err("Can't open %s\n", path);
>> >> +            return -1;
>> >> +    }
>> >> +
>> >> +    num = -1;
>> >> +    while (fgets(buf, sizeof(buf), proc_file)) {
>> >> +            num = parse_ofd_lock(buf, lck);
>> >> +            if (num <= 0)
>> >> +                    break;
>> >> +    }
>> >> +
>> >> +    if (fclose(proc_file)) {
>> >> +            pr_err("Can't close %s\n", path);
>> >> +            return -1;
>> >> +    }
>> >> +    return num;
>> >> +}
>> >> +
>> >> +static int check_lock_exists(const char *filename, struct flock *lck)
>> >> +{
>> >> +    int ret = -1;
>> >> +    int fd;
>> >> +
>> >> +    fd = open(filename, O_RDWR, 0666);
>> >> +
>> >> +    if (lck->l_type == F_RDLCK) {
>> >> +            /* check, that there is no write lock */
>> >> +            ret = fcntl(fd, F_OFD_GETLK, lck);
>> >> +            if (ret) {
>> >> +                    pr_err("fcntl failed (%i)\n", ret);
>> >> +                    goto out;
>> >> +            }
>> >> +            if (lck->l_type != F_UNLCK) {
>> >> +                    pr_err("OFD lock type do not match\n");
>> >> +                    goto out;
>> >> +            }
>> >> +    }
>> >> +
>> >> +    /* check, that lock is set */
>> >> +    lck->l_type = F_WRLCK;
>> >> +    ret = fcntl(fd, F_OFD_GETLK, lck);
>> >> +    if (ret) {
>> >> +            pr_err("fcntl failed (%i)\n", ret);
>> >> +            goto out;
>> >> +    }
>> >> +    if (lck->l_type == F_UNLCK) {
>> >> +            pr_err("Lock not found\n");
>> >> +            goto out;
>> >> +    }
>> >> +
>> >> +    ret = 0;
>> >> +out:
>> >> +    if (close(fd))
>> >> +            return -1;
>> >> +    return ret;
>> >> +}
>> >> +
>> >> +static int check_file_locks_match(struct flock *orig_lck, struct
>> flock *lck)
>> >> +{
>> >> +    return orig_lck->l_start == lck->l_start &&
>> >> +            orig_lck->l_len == lck->l_len &&
>> >> +            orig_lck->l_type == lck->l_type;
>> >> +}
>> >> +
>> >> +static int check_file_lock_restored(int pid, int fd, struct flock
>> *lck)
>> >> +{
>> >> +    struct flock lck_restored;
>> >> +
>> >> +    if (read_fd_ofd_lock(pid, fd, &lck_restored))
>> >> +            return -1;
>> >> +
>> >> +    if (!check_file_locks_match(lck, &lck_restored)) {
>> >> +            pr_err("Can't restore file lock (fd: %i)\n", fd);
>> >> +            return -1;
>> >> +    }
>> >> +    return 0;
>> >> +}
>> >> +
>> >> +#endif /* ZDTM_OFD_FILE_LOCKS_H_ */
>> >>
>> >
>>
>>
>
>
> --
> Best regards,
> Eugene Batalov.
>



-- 
Best regards,
Eugene Batalov.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openvz.org/pipermail/criu/attachments/20161230/0103e97d/attachment-0001.html>


More information about the CRIU mailing list