From 34c9119acdf543d8b51a87cc47ebb788caf0fc37 Mon Sep 17 00:00:00 2001 From: Begunkov Pavel Date: Tue, 20 Dec 2016 13:24:38 +0300 Subject: [PATCH] locks: Add ofd locks c/r OFD locks logic reuses existing locks c/r functionality. https://github.com/xemul/criu/issues/42 travis-ci: success for series starting with [1/2] locks: Add ofd locks c/r Signed-off-by: Begunkov Pavel Signed-off-by: Eugene Batalov Signed-off-by: Pavel Emelyanov --- 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 11d8a1949..55564f749 100644 --- a/criu/file-lock.c +++ b/criu/file-lock.c @@ -205,6 +205,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; @@ -233,11 +284,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. @@ -248,7 +299,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) @@ -313,6 +368,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 5c1bb5b61..c3f2dabf7 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 a86d31769..8ca7c7ced 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;