[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