From 6d66dd5d89f48026fd8a7149bfbb83669e7ff508 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Thu, 2 May 2019 02:34:41 +0100 Subject: [PATCH] zdtm/ia32: fcntl() wrapper for old glibc(s) A bit nasty, but does the job to run ofd tests on glibc < v2.28. Other way would be to update glibc on Travis-CI ia32 tests, but I thought someone might want to run the tests outside Travis-CI. Fixes: #745 Signed-off-by: Dmitry Safonov Signed-off-by: Andrei Vagin --- test/zdtm/static/file_locks06.c | 2 +- test/zdtm/static/file_locks07.c | 2 +- test/zdtm/static/file_locks08.c | 2 +- test/zdtm/static/ofd_file_locks.c | 60 +++++++++++++++++++++++++++++-- test/zdtm/static/ofd_file_locks.h | 1 + 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/test/zdtm/static/file_locks06.c b/test/zdtm/static/file_locks06.c index 9bc70c47d..780fb07ea 100644 --- a/test/zdtm/static/file_locks06.c +++ b/test/zdtm/static/file_locks06.c @@ -26,7 +26,7 @@ int init_lock(int *fd, struct flock *lck) lck->l_len = 0; lck->l_pid = 0; - if (fcntl(*fd, F_OFD_SETLK, lck) < 0) { + if (zdtm_fcntl(*fd, F_OFD_SETLK, lck) < 0) { pr_perror("Can't set ofd lock"); return -1; } diff --git a/test/zdtm/static/file_locks07.c b/test/zdtm/static/file_locks07.c index b36f23011..2fe169fcf 100644 --- a/test/zdtm/static/file_locks07.c +++ b/test/zdtm/static/file_locks07.c @@ -45,7 +45,7 @@ int init_file_locks(void) } for (i = 0; i < FILE_NUM; ++i) - if (fcntl(fds[i], F_OFD_SETLKW, &lcks[i]) < 0) { + if (zdtm_fcntl(fds[i], F_OFD_SETLKW, &lcks[i]) < 0) { pr_perror("Can't set ofd lock"); return -1; } diff --git a/test/zdtm/static/file_locks08.c b/test/zdtm/static/file_locks08.c index 2d25b4b09..fea8d9e7e 100644 --- a/test/zdtm/static/file_locks08.c +++ b/test/zdtm/static/file_locks08.c @@ -28,7 +28,7 @@ int init_file_lock(int *fd, struct flock *lck) 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) { + if (zdtm_fcntl(*fd, F_OFD_SETLKW, lck) < 0) { pr_perror("Can't set ofd lock"); return -1; } diff --git a/test/zdtm/static/ofd_file_locks.c b/test/zdtm/static/ofd_file_locks.c index c4a633625..5b19532f8 100644 --- a/test/zdtm/static/ofd_file_locks.c +++ b/test/zdtm/static/ofd_file_locks.c @@ -86,7 +86,7 @@ int check_lock_exists(const char *filename, struct flock *lck) if (lck->l_type == F_RDLCK) { /* check, that there is no write lock */ - ret = fcntl(fd, F_OFD_GETLK, lck); + ret = zdtm_fcntl(fd, F_OFD_GETLK, lck); if (ret) { pr_err("fcntl failed (%i)\n", ret); goto out; @@ -99,7 +99,7 @@ int check_lock_exists(const char *filename, struct flock *lck) /* check, that lock is set */ lck->l_type = F_WRLCK; - ret = fcntl(fd, F_OFD_GETLK, lck); + ret = zdtm_fcntl(fd, F_OFD_GETLK, lck); if (ret) { pr_err("fcntl failed (%i)\n", ret); goto out; @@ -136,3 +136,59 @@ int check_file_lock_restored(int pid, int fd, struct flock *lck) } return 0; } + +/* + * fcntl() wrapper for ofd locks. + * + * Kernel requires ia32 processes to use fcntl64() syscall for ofd: + * COMPAT_SYSCALL_DEFINE3(fcntl, [..]) + * { + * switch (cmd) { + * case F_GETLK64: + * case F_SETLK64: + * case F_SETLKW64: + * case F_OFD_GETLK: + * case F_OFD_SETLK: + * case F_OFD_SETLKW: + * return -EINVAL; + * } + * + * Glibc does all the needed wraps for fcntl(), but only from v2.28. + * To make ofd tests run on the older glibc's - provide zdtm wrap. + * + * Note: we don't need the wraps in CRIU itself as parasite/restorer + * run in 64-bit mode as long as possible, including the time to play + * with ofd (and they are dumped from CRIU). + */ +int zdtm_fcntl(int fd, int cmd, struct flock *f) +{ +#if defined(__i386__) +#ifndef __NR_fcntl64 +# define __NR_fcntl64 221 +#endif + struct flock64 f64 = {}; + int ret; + + switch (cmd) { + case F_OFD_SETLK: + case F_OFD_SETLKW: + f64.l_type = f->l_type; + f64.l_whence = f->l_whence; + f64.l_start = f->l_start; + f64.l_len = f->l_len; + f64.l_pid = f->l_pid; + return syscall(__NR_fcntl64, fd, cmd, &f64); + case F_OFD_GETLK: + ret = syscall(__NR_fcntl64, fd, cmd, &f64); + f->l_type = f64.l_type; + f->l_whence = f64.l_whence; + f->l_start = f64.l_start; + f->l_len = f64.l_len; + f->l_pid = f64.l_pid; + return ret; + default: + break; + } +#endif + return fcntl(fd, cmd, f); +} diff --git a/test/zdtm/static/ofd_file_locks.h b/test/zdtm/static/ofd_file_locks.h index 6978446df..1b206a238 100644 --- a/test/zdtm/static/ofd_file_locks.h +++ b/test/zdtm/static/ofd_file_locks.h @@ -16,5 +16,6 @@ extern int check_lock_exists(const char *filename, struct flock *lck); extern int check_file_lock_restored(int pid, int fd, struct flock *lck); +extern int zdtm_fcntl(int fd, int cmd, struct flock *f); #endif /* ZDTM_OFD_FILE_LOCKS_H_ */