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

Pavel Emelyanov xemul at virtuozzo.com
Mon Jan 9 00:44:03 PST 2017


On 01/04/2017 02:40 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.
> 
> 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 +
>  4 files changed, 96 insertions(+)
>  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..f4824ae
> --- /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;
> +	}
> +
> +	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);
> +	socklen_t len = sizeof(id);
> +	int fd;
> +
> +	if (getsockopt(sk, SOL_SOCKET, SO_PEEK_OFF, &id, &len)) {

Maybe setsockopt?

> +		pr_perror("Unable to a peek offset");
> +		return -1;
> +	}
> +
> +	fd = recv_fd(sk);
> +	if (fd < 0)
> +		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
>  };
> 



More information about the CRIU mailing list