[CRIU] [PATCH 2/6] fdstore: add a storage for file descriptors (v2)

Pavel Emelyanov xemul at virtuozzo.com
Mon Feb 6 02:05:53 PST 2017


On 01/10/2017 05:00 AM, Andrei Vagin wrote:
> From: Andrei Vagin <avagin at virtuozzo.com>
> 
> We need a storage for file descriptors which is shared between processes
> and doesn't use a lot of file descriptors. We are going to use it on
> restore and if it will use file descriptors, we will have to find
> descriptors which don't used by all restored processes to not confilict
> with their descriptors.
> 
> There are two solutions. The first one is a service (process) which
> handles to command push_fd(id, fd) and pop_fd(id, fd).
> 
> Another solution is to save descriptros in a unix socket.  It requires
> only one extra descriptor which we can register as a service fd. Each
> unix socket has a buffer and can fit a number of file descriptros. We
> can use SK_PEEK_OFF and MSG_PEEK to get file descriptros from a socket
> as many times as we need.
> 
> This patch implements the second solution.
> 
> v2: call recvmsg with MSG_PEEK
> Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
> ---
>  criu/Makefile.crtools     |  1 +
>  criu/fdstore.c            | 86 +++++++++++++++++++++++++++++++++++++++++++++++
>  criu/include/fdstore.h    |  8 +++++
>  criu/include/servicefd.h  |  1 +
>  criu/parasite-syscall.c   |  2 +-
>  include/common/scm-code.c |  4 +--
>  include/common/scm.h      |  4 +--
>  7 files changed, 101 insertions(+), 5 deletions(-)
>  create mode 100644 criu/fdstore.c
>  create mode 100644 criu/include/fdstore.h
> 
> diff --git a/criu/Makefile.crtools b/criu/Makefile.crtools
> index 8188129..b85d776 100644
> --- a/criu/Makefile.crtools
> +++ b/criu/Makefile.crtools
> @@ -79,6 +79,7 @@ obj-y			+= uts_ns.o
>  obj-y			+= path.o
>  obj-y			+= autofs.o
>  obj-y			+= uffd.o
> +obj-y			+= fdstore.o
>  
>  ifeq ($(VDSO),y)
>  obj-y			+= pie-util-vdso.o
> diff --git a/criu/fdstore.c b/criu/fdstore.c
> new file mode 100644
> index 0000000..337a821
> --- /dev/null
> +++ b/criu/fdstore.c
> @@ -0,0 +1,86 @@
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <sys/un.h>
> +#include <sys/stat.h>
> +#include <unistd.h>
> +#include <stdio.h>
> +
> +#include "common/scm.h"
> +#include "servicefd.h"
> +#include "fdstore.h"
> +#include "xmalloc.h"
> +#include "log.h"
> +
> +static int next_id;
> +
> +int fdstore_init(void)
> +{
> +	struct sockaddr_un addr;
> +	unsigned int addrlen;
> +	struct stat st;
> +	int sk, ret;
> +
> +	sk = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0);
> +	if (sk < 0) {
> +		pr_perror("Unable to create a socket");
> +		return -1;
> +	}
> +
> +	if (fstat(sk, &st)) {
> +		pr_perror("Unable to stat a file descriptor");
> +		close(sk);
> +		return -1;
> +	}
> +
> +	addr.sun_family = AF_UNIX;
> +	addrlen = snprintf(addr.sun_path, sizeof(addr.sun_path), "X/criu-fdstore-%"PRIx64, st.st_ino);
> +	addrlen += sizeof(addr.sun_family);
> +
> +	addr.sun_path[0] = 0;
> +	if (bind(sk, (struct sockaddr *) &addr, addrlen)) {
> +		pr_perror("Unable to bind a socket");
> +		close(sk);
> +		return -1;
> +	}
> +	if (connect(sk, (struct sockaddr *) &addr, addrlen)) {
> +		pr_perror("Unable to connect a socket");
> +		close(sk);
> +		return -1;
> +	}

Plz, add a good comment describing why you connect socket to self.

> +
> +	ret = install_service_fd(FDSTORE_SK_OFF, sk);
> +	close(sk);
> +	if (ret < 0)
> +		return -1;
> +
> +	return 0;
> +}
> +
> +int fdstore_add(int fd)
> +{
> +	int sk = get_service_fd(FDSTORE_SK_OFF);
> +
> +	if (send_fd(sk, NULL, 0, fd))
> +		return -1;
> +
> +	next_id++;
> +
> +	return next_id - 1;
> +}
> +
> +int fdstore_get(int id)
> +{
> +	int sk = get_service_fd(FDSTORE_SK_OFF);
> +	int fd;
> +
> +	if (setsockopt(sk, SOL_SOCKET, SO_PEEK_OFF, &id, sizeof(id))) {
> +		pr_perror("Unable to a peek offset");
> +		return -1;
> +	}
> +
> +	if (recv_fds(sk, &fd, 1, NULL, 0, MSG_PEEK) < 0) {
> +		pr_perror("Unable to get a file descriptor with the %d id", id);
> +		return -1;
> +	}
> +	return fd;
> +}
> diff --git a/criu/include/fdstore.h b/criu/include/fdstore.h
> new file mode 100644
> index 0000000..b406cdd
> --- /dev/null
> +++ b/criu/include/fdstore.h
> @@ -0,0 +1,8 @@
> +#ifndef __CRIU_FDSTORE_H__
> +#define __CRIU_FDSTORE_H__
> +
> +int fdstore_init(void);
> +int fdstore_add(int fd);
> +int fdstore_get(int id);
> +
> +#endif
> diff --git a/criu/include/servicefd.h b/criu/include/servicefd.h
> index 1b48e90..3e0e376 100644
> --- a/criu/include/servicefd.h
> +++ b/criu/include/servicefd.h
> @@ -22,6 +22,7 @@ enum sfd_type {
>  	TRANSPORT_FD_OFF, /* to transfer file descriptors */
>  	LAZY_PAGES_SK_OFF, /* socket for communication with lazy-pages daemon */
>  	RPC_SK_OFF,
> +	FDSTORE_SK_OFF,
>  
>  	SERVICE_FD_MAX
>  };
> diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
> index a525324..f0ff991 100644
> --- a/criu/parasite-syscall.c
> +++ b/criu/parasite-syscall.c
> @@ -402,7 +402,7 @@ int parasite_drain_fds_seized(struct parasite_ctl *ctl,
>  	}
>  
>  	sk = compel_rpc_sock(ctl);
> -	ret = recv_fds(sk, lfds, nr_fds, opts, sizeof(struct fd_opts));
> +	ret = recv_fds(sk, lfds, nr_fds, opts, sizeof(struct fd_opts), 0);
>  	if (ret)
>  		pr_err("Can't retrieve FDs from socket\n");
>  
> diff --git a/include/common/scm-code.c b/include/common/scm-code.c
> index 504c972..9f21418 100644
> --- a/include/common/scm-code.c
> +++ b/include/common/scm-code.c
> @@ -75,7 +75,7 @@ int send_fds(int sock, struct sockaddr_un *saddr, int len,
>  	return 0;
>  }
>  
> -int recv_fds(int sock, int *fds, int nr_fds, void *data, unsigned ch_size)
> +int recv_fds(int sock, int *fds, int nr_fds, void *data, unsigned ch_size, int flags)
>  {
>  	struct scm_fdset fdset;
>  	struct cmsghdr *cmsg;
> @@ -88,7 +88,7 @@ int recv_fds(int sock, int *fds, int nr_fds, void *data, unsigned ch_size)
>  		min_fd = min(CR_SCM_MAX_FD, nr_fds - i);
>  		scm_fdset_init_chunk(&fdset, min_fd, data, ch_size);
>  
> -		ret = __sys(recvmsg)(sock, &fdset.hdr, 0);
> +		ret = __sys(recvmsg)(sock, &fdset.hdr, flags);
>  		if (ret <= 0)
>  			return ret ? : -1;
>  
> diff --git a/include/common/scm.h b/include/common/scm.h
> index 3874d1c..6110409 100644
> --- a/include/common/scm.h
> +++ b/include/common/scm.h
> @@ -28,7 +28,7 @@ struct scm_fdset {
>  extern int send_fds(int sock, struct sockaddr_un *saddr, int len,
>  		int *fds, int nr_fds, void *data, unsigned ch_size);
>  extern int recv_fds(int sock, int *fds, int nr_fds,
> -		void *data, unsigned ch_size);
> +		void *data, unsigned ch_size, int flags);
>  
>  static inline int send_fd(int sock, struct sockaddr_un *saddr, int saddr_len, int fd)
>  {
> @@ -39,7 +39,7 @@ static inline int recv_fd(int sock)
>  {
>  	int fd, ret;
>  
> -	ret = recv_fds(sock, &fd, 1, NULL, 0);
> +	ret = recv_fds(sock, &fd, 1, NULL, 0, 0);
>  	if (ret)
>  		return -1;
>  
> 



More information about the CRIU mailing list