[1/5] zdtm/ia32: fcntl() wrapper for old glibc(s)

Submitted by Dmitry Safonov on May 2, 2019, 1:34 a.m.

Details

Message ID 20190502013445.528-2-dima@arista.com
State Accepted
Series "ia32/zdtm: A couple of 32bit fixes"
Commit 26d21236250b1951e9a0aa2a92e48710dde22d6e
Headers show

Commit Message

Dmitry Safonov May 2, 2019, 1:34 a.m.
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.

Signed-off-by: Dmitry Safonov <dima@arista.com>
---
 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(-)

Patch hide | download patch | download mbox

diff --git a/test/zdtm/static/file_locks06.c b/test/zdtm/static/file_locks06.c
index 9bc70c47d63b..780fb07eaa32 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 b36f23011fcf..2fe169fcfb31 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 2d25b4b09719..fea8d9e7ee06 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 c4a6336250ea..5b19532f8bba 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 6978446dfea0..1b206a238bf4 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_ */