[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