[CRIU] [PATCH 1/2] locks: Add ofd locks c/r
Andrei Vagin
avagin at virtuozzo.com
Wed Jan 4 17:47:37 PST 2017
On Tue, Dec 20, 2016 at 01:24:38PM +0300, Pavel Begunkov wrote:
> 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);
CID 173734 (#1 of 1): Unchecked return value from library (CHECKED_RETURN)
7. check_return: Calling fcntl(lfd, 37, &lck) without checking return
value. This library function may fail and return an error code.
> + }
> +
> + 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
>
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
More information about the CRIU
mailing list