[CRIU] [PATCHv2 2/5] locks: Add c/r of breaking leases (kernel>=v4.1)

Pavel Emelyanov xemul at virtuozzo.com
Tue Aug 15 17:46:40 MSK 2017


On 08/14/2017 02:49 AM, Pavel Begunkov wrote:
> Leases can be taken out only on regular files. In order to restore
> breaking lease it break restored lease by opening a file with which
> lease is associated.

But if the lease was broken, then there should be a file in
the images, that is opened. Why opening it one more time?

More comments inline.

> Signed-off-by: Pavel Begunkov <asml.silence at gmail.com>
> ---
>  criu/file-lock.c         | 99 ++++++++++++++++++++++++++++++++++++++++++++++--
>  criu/files.c             |  1 +
>  criu/include/file-lock.h |  3 ++
>  criu/proc_parse.c        |  7 ++--
>  4 files changed, 103 insertions(+), 7 deletions(-)
> 
> diff --git a/criu/file-lock.c b/criu/file-lock.c
> index 92d8bd394..0c5da70ca 100644
> --- a/criu/file-lock.c
> +++ b/criu/file-lock.c
> @@ -18,6 +18,8 @@
>  #include "proc_parse.h"
>  #include "servicefd.h"
>  #include "file-lock.h"
> +#include "pstree.h"
> +#include "files-reg.h"
>  
>  struct file_lock_rst {
>  	FileLockEntry *fle;
> @@ -332,6 +334,97 @@ int note_file_lock(struct pid *pid, int fd, int lfd, struct fd_parms *p)
>  	return 0;
>  }
>  
> +static int open_break_cb(int ns_root_fd, struct reg_file_info *rfi, void *arg)
> +{
> +	int fd, flags = *(int *)arg | O_NONBLOCK;
> +
> +	fd = openat(ns_root_fd, rfi->path, flags);
> +	if (fd >= 0) {
> +		pr_err("Conflicting lease wasn't found\n");
> +		close(fd);
> +		return -1;
> +	}
> +	if (errno != EWOULDBLOCK) {
> +		pr_perror("Can't open file to break lease\n");
> +		return -1;
> +	}
> +	return 0;
> +}
> +
> +static int set_lease_for_breaking(int fd, int fd_type)
> +{
> +	int lease_type;
> +
> +	if (fd_type == O_RDONLY) {
> +		lease_type = F_RDLCK;
> +	} else if (fd_type == O_WRONLY) {
> +		lease_type = F_WRLCK;
> +	} else {
> +		pr_err("Incompatible with lease file type (%i)\n", fd_type);
> +		return -1;
> +	}
> +
> +	if (fcntl(fd, F_SETLEASE, lease_type) < 0) {
> +		pr_perror("Can't set lease to fd %#x\n", fd);
> +		return -1;
> +	}
> +	return 0;
> +}
> +
> +static struct fdinfo_list_entry *find_fd(struct pstree_item *task, int fd)

There's already such a helper in files.c

> +{
> +	struct list_head *head = &rsti(task)->fds;
> +	struct fdinfo_list_entry *fle;
> +
> +	list_for_each_entry_reverse(fle, head, ps_list) {
> +		if (fle->fe->fd == fd)
> +			return fle;
> +	}
> +	return NULL;
> +}
> +
> +static int restore_breaking_file_lease(FileLockEntry *fle)
> +{
> +	struct fdinfo_list_entry *fdle;
> +	int break_flags;
> +	int lease_break_type = fle->type & (~LEASE_BREAKING);
> +
> +	fdle = find_fd(current, fle->fd);
> +	if (fdle == NULL) {
> +		pr_err("Can't get file description\n");
> +		return -1;
> +	}
> +
> +	if (set_lease_for_breaking(fle->fd, fdle->desc->ops->type))
> +		return -1;
> +
> +	if (lease_break_type == F_UNLCK) {
> +		break_flags = O_WRONLY;
> +	} else if (lease_break_type == F_RDLCK) {
> +		break_flags = O_RDONLY;
> +	} else {
> +		pr_err("Incorrect breaking type of lease\n");
> +		return -1;
> +	}
> +	if (open_path(fdle->desc, open_break_cb, (void *)&break_flags) < 0)
> +		return -1;
> +	return 0;

Just return open_path();?

> +}
> +
> +static int restore_file_lease(FileLockEntry *fle)
> +{
> +	int ret;
> +
> +	if (fle->type & LEASE_BREAKING) {
> +		return restore_breaking_file_lease(fle);

The restore_breaking_file_lease() leaves the lease in the "generated" state,
not in the fle->type one. Is that intentional?

> +	} else {
> +		ret = fcntl(fle->fd, F_SETLEASE, fle->type);
> +		if (ret < 0)
> +			pr_perror("Can't restore non broken lease");
> +		return ret;
> +	}
> +}
> +
>  static int restore_file_lock(FileLockEntry *fle)
>  {
>  	int ret = -1;
> @@ -399,11 +492,9 @@ static int restore_file_lock(FileLockEntry *fle)
>  			goto err;
>  		}
>  	} else if (fle->flag & FL_LEASE) {
> -		ret = fcntl(fle->fd, F_SETLEASE, fle->type);
> -		if (ret < 0) {
> -			pr_perror("Can't set lease!\n");
> +		ret = restore_file_lease(fle);
> +		if (ret < 0)
>  			goto err;
> -		}
>  	} else {
>  		pr_err("Unknown file lock style!\n");
>  		goto err;
> diff --git a/criu/files.c b/criu/files.c
> index 01cd4c0e9..2c3389e3f 100644
> --- a/criu/files.c
> +++ b/criu/files.c
> @@ -14,6 +14,7 @@
>  #include <stdlib.h>
>  
>  #include "types.h"
> +#include "kerndat.h"
>  #include "files.h"
>  #include "file-ids.h"
>  #include "files-reg.h"
> diff --git a/criu/include/file-lock.h b/criu/include/file-lock.h
> index f70739adb..7280e0b55 100644
> --- a/criu/include/file-lock.h
> +++ b/criu/include/file-lock.h
> @@ -38,6 +38,9 @@
>  #define LOCK_WRITE	128	/* which allows concurrent write operations */
>  #define LOCK_RW		192	/* which allows concurrent read & write ops */
>  
> +/* for leases */
> +#define LEASE_BREAKING	4
> +
>  struct file_lock {
>  	long long	fl_id;
>  	int		fl_kind;
> diff --git a/criu/proc_parse.c b/criu/proc_parse.c
> index d3893272c..89be4ceb5 100644
> --- a/criu/proc_parse.c
> +++ b/criu/proc_parse.c
> @@ -1996,6 +1996,10 @@ static int parse_file_lock_buf(char *buf, struct file_lock *fl,
>  	else
>  		fl->fl_kind = FL_UNKNOWN;
>  
> +	if (fl->fl_kind == FL_LEASE && !strcmp(fl_type, "BREAKING")) {
> +		fl->fl_ltype |= LEASE_BREAKING;
> +	}
> +
>  	if (!strcmp(fl_type, "MSNFS")) {
>  		fl->fl_ltype |= LOCK_MAND;
>  
> @@ -2009,9 +2013,6 @@ static int parse_file_lock_buf(char *buf, struct file_lock *fl,
>  			pr_err("Unknown lock option!\n");
>  			return -1;
>  		}
> -	} else if (fl->fl_kind == FL_LEASE && !strcmp(fl_type, "BREAKING")) {
> -		pr_err("Breaking leases are not supported (%d): %s\n",
> -			num, buf);
>  	} else {
>  		if (!strcmp(fl_option, "UNLCK")) {
>  			fl->fl_ltype |= F_UNLCK;
> 



More information about the CRIU mailing list