[CRIU] [PATCH 1/2] locks: Add ofd locks c/r

Pavel Begunkov asml.silence at gmail.com
Tue Dec 20 02:24:38 PST 2016


From: Begunkov Pavel <asml.silence at gmail.com>

OFD locks logic reuses existing locks c/r functionality.

Signed-off-by: Begunkov Pavel <asml.silence at gmail.com>
Signed-off-by: Eugene Batalov <eabatalov89 at gmail.com>
---
 criu/file-lock.c         | 80 ++++++++++++++++++++++++++++++++++++++++++++++--
 criu/include/file-lock.h |  8 +++++
 criu/proc_parse.c        |  2 ++
 3 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/criu/file-lock.c b/criu/file-lock.c
index 1ab1e58..fbb963b 100644
--- a/criu/file-lock.c
+++ b/criu/file-lock.c
@@ -204,6 +204,57 @@ static int lock_check_fd(int lfd, struct file_lock *fl)
 	return 1;
 }
 
+static int lock_ofd_check_fd(int lfd, struct file_lock *fl)
+{
+	int ret;
+
+	struct flock lck = {
+		.l_whence = SEEK_SET,
+		.l_type   = F_WRLCK,
+		.l_start  = fl->start
+	};
+	if (strcmp(fl->end, "EOF")) {
+		unsigned long end;
+
+		ret = sscanf(fl->end, "%lu", &end);
+		if (ret <= 0) {
+			pr_err("Invalid lock entry\n");
+			return -1;
+		}
+		lck.l_len = end - fl->start + 1;
+	} else {
+		lck.l_len = 0;
+	}
+
+	ret = fcntl(lfd, F_OFD_SETLK, &lck);
+	pr_debug("   `- %d/%d\n", ret, errno);
+	if (ret != 0) {
+		if (errno != EAGAIN) {
+			pr_err("Bogus lock test result %d\n", ret);
+			return -1;
+		}
+
+		return 0;
+	} else {
+		/*
+		 * The ret == 0 means, that new lock doesn't conflict
+		 * with any others on the file. But since we do know,
+		 * that there should be some other one (file is found
+		 * in /proc/locks), it means that the lock is already
+		 * on file pointed by fd.
+		 */
+		pr_debug("   `- downgrading lock back\n");
+		if (fl->fl_ltype & LOCK_WRITE)
+			lck.l_type = F_WRLCK;
+		else
+			lck.l_type = F_RDLCK;
+
+		fcntl(lfd, F_OFD_SETLK, &lck);
+	}
+
+	return 1;
+}
+
 int note_file_lock(struct pid *pid, int fd, int lfd, struct fd_parms *p)
 {
 	struct file_lock *fl;
@@ -232,11 +283,11 @@ int note_file_lock(struct pid *pid, int fd, int lfd, struct fd_parms *p)
 			 */
 			if (fl->fl_owner != pid->real)
 				continue;
-		} else /* fl->fl_kind == FL_FLOCK */ {
+		} else /* fl->fl_kind == FL_FLOCK || fl->fl_kind == FL_OFD */ {
 			int ret;
 
 			/*
-			 * FLOCKs can be inherited across fork,
+			 * OFD locks & FLOCKs can be inherited across fork,
 			 * thus we can have any task as lock
 			 * owner. But the creator is preferred
 			 * anyway.
@@ -247,7 +298,11 @@ int note_file_lock(struct pid *pid, int fd, int lfd, struct fd_parms *p)
 				continue;
 
 			pr_debug("Checking lock holder %d:%d\n", pid->real, fd);
-			ret = lock_check_fd(lfd, fl);
+			if (fl->fl_kind == FL_FLOCK)
+				ret = lock_check_fd(lfd, fl);
+			else
+				ret = lock_ofd_check_fd(lfd, fl);
+
 			if (ret < 0)
 				return ret;
 			if (ret == 0)
@@ -312,6 +367,25 @@ static int restore_file_lock(FileLockEntry *fle)
 			pr_err("Can not set posix lock!\n");
 			goto err;
 		}
+	} else if (fle->flag & FL_OFD) {
+		struct flock flk = {
+			.l_whence = SEEK_SET,
+			.l_start  = fle->start,
+			.l_len    = fle->len,
+			.l_pid    = 0,
+			.l_type   = fle->type
+		};
+
+		pr_info("(ofd)flag: %d, type: %d, pid: %d, fd: %d, "
+				"start: %8"PRIx64", len: %8"PRIx64"\n",
+				fle->flag, fle->type, fle->pid, fle->fd,
+				fle->start, fle->len);
+
+		ret = fcntl(fle->fd, F_OFD_SETLK, &flk);
+		if (ret < 0) {
+			pr_err("Can not set ofd lock!\n");
+			goto err;
+		}
 	} else {
 		pr_err("Unknown file lock style!\n");
 		goto err;
diff --git a/criu/include/file-lock.h b/criu/include/file-lock.h
index 5c1bb5b..c3f2dab 100644
--- a/criu/include/file-lock.h
+++ b/criu/include/file-lock.h
@@ -9,6 +9,7 @@
 #define FL_UNKNOWN	-1
 #define FL_POSIX	1
 #define FL_FLOCK	2
+#define FL_OFD		4
 
 /* for posix fcntl() and lockf() */
 #ifndef F_RDLCK
@@ -17,6 +18,13 @@
 #define F_UNLCK		2
 #endif
 
+/* for OFD locks fcntl() */
+#ifndef F_OFD_GETLK
+#define F_OFD_GETLK	36
+#define F_OFD_SETLK	37
+#define F_OFD_SETLKW	38
+#endif
+
 /* operations for bsd flock(), also used by the kernel implementation */
 #define LOCK_SH		1	/* shared lock */
 #define LOCK_EX		2	/* exclusive lock */
diff --git a/criu/proc_parse.c b/criu/proc_parse.c
index 7c48b33..1f0bff8 100644
--- a/criu/proc_parse.c
+++ b/criu/proc_parse.c
@@ -1973,6 +1973,8 @@ static int parse_file_lock_buf(char *buf, struct file_lock *fl,
 		fl->fl_kind = FL_POSIX;
 	else if (!strcmp(fl_flag, "FLOCK"))
 		fl->fl_kind = FL_FLOCK;
+	else if (!strcmp(fl_flag, "OFDLCK"))
+		fl->fl_kind = FL_OFD;
 	else
 		fl->fl_kind = FL_UNKNOWN;
 
-- 
2.10.0



More information about the CRIU mailing list