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

Andrei Vagin avagin at virtuozzo.com
Mon Jan 9 09:35:34 PST 2017


On Mon, Jan 09, 2017 at 11:44:03AM +0300, Pavel Emelyanov wrote:
> 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?

Good catch;)
> 
> > +		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