[CRIU] [PATCH RFC 08/12] files: Make sending fds to peers async
Kirill Tkhai
ktkhai at virtuozzo.com
Fri Oct 28 05:53:43 PDT 2016
Don't wait for "prepare" stage of every peer's fd. Just
send everything to peer's global transport_fd, and peer
will find appropriate fd, it needs at the moment.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/autofs.c | 1 -
criu/files.c | 98 ++++++++++----------------------------------------
criu/include/files.h | 1 -
3 files changed, 20 insertions(+), 80 deletions(-)
diff --git a/criu/autofs.c b/criu/autofs.c
index 467ed16..113b5ca 100644
--- a/criu/autofs.c
+++ b/criu/autofs.c
@@ -876,7 +876,6 @@ static int autofs_create_fle(struct pstree_item *task, FdinfoEntry *fe,
return -1;
le = (void *)ALIGN((long)le, sizeof(int));
- futex_init(&le->real_pid);
le->pid = task->pid.virt;
le->fe = fe;
le->received = false;
diff --git a/criu/files.c b/criu/files.c
index 338d9d2..7683b1c 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -694,7 +694,6 @@ static int collect_fd(int pid, FdinfoEntry *e, struct rst_info *rst_info)
if (!new_le)
return -1;
- futex_init(&new_le->real_pid);
new_le->pid = pid;
new_le->fe = e;
new_le->received = false;
@@ -872,20 +871,18 @@ struct fd_open_state {
bool required;
};
-static int open_transport_fd(int pid, struct fdinfo_list_entry *fle);
static int open_fd(int pid, struct fdinfo_list_entry *fle);
static int receive_fd(int pid, struct fdinfo_list_entry *fle);
static int post_open_fd(int pid, struct fdinfo_list_entry *fle);
static struct fd_open_state states[] = {
- { "prepare", open_transport_fd, true,},
{ "create", open_fd, true,},
{ "receive", receive_fd, false,},
{ "post_create", post_open_fd, false,},
};
-#define want_recv_stage() do { states[2].required = true; } while (0)
-#define want_post_open_stage() do { states[3].required = true; } while (0)
+#define want_recv_stage() do { states[1].required = true; } while (0)
+#define want_post_open_stage() do { states[2].required = true; } while (0)
static void transport_name_gen(struct sockaddr_un *addr, int *len,
int pid, int fd)
@@ -896,68 +893,6 @@ static void transport_name_gen(struct sockaddr_un *addr, int *len,
*addr->sun_path = '\0';
}
-static int should_open_transport(FdinfoEntry *fe, struct file_desc *fd)
-{
- if (fd->ops->want_transport)
- return fd->ops->want_transport(fe, fd);
- else
- return 0;
-}
-
-static int open_transport_fd(int pid, struct fdinfo_list_entry *fle)
-{
- struct fdinfo_list_entry *flem;
- struct sockaddr_un saddr;
- int sock;
- int ret, sun_len;
-
- flem = file_master(fle->desc);
-
- if (flem->pid == pid) {
- if (flem->fe->fd != fle->fe->fd)
- /* dup-ed file. Will be opened in the open_fd */
- return 0;
-
- if (!should_open_transport(fle->fe, fle->desc))
- /* pure master file */
- return 0;
-
- /*
- * some master file, that wants a transport, e.g.
- * a pipe or unix socket pair 'slave' end
- */
- }
-
- transport_name_gen(&saddr, &sun_len, getpid(), fle->fe->fd);
-
- pr_info("\t\tCreate transport fd %s\n", saddr.sun_path + 1);
-
-
- sock = socket(PF_UNIX, SOCK_DGRAM, 0);
- if (sock < 0) {
- pr_perror("Can't create socket");
- return -1;
- }
- ret = bind(sock, (struct sockaddr *)&saddr, sun_len);
- if (ret < 0) {
- pr_perror("Can't bind unix socket %s", saddr.sun_path + 1);
- goto err;
- }
-
- ret = reopen_fd_as(fle->fe->fd, sock);
- if (ret < 0)
- goto err;
-
- pr_info("\t\tWake up fdinfo pid=%d fd=%d\n", fle->pid, fle->fe->fd);
- futex_set_and_wake(&fle->real_pid, getpid());
- want_recv_stage();
-
- return 0;
-err:
- close(sock);
- return -1;
-}
-
static bool insane_fle(struct fdinfo_list_entry *alien_fle)
{
struct fdinfo_list_entry *fle;
@@ -973,22 +908,20 @@ static int recv_further_fle(struct fdinfo_list_entry *fle, int fd)
{
BUG_ON(fle->received);
fle->received = true;
- if (close(fle->fe->fd) < 0) {
- pr_perror("Can't close transport fd\n");
- return -1;
- }
return reopen_fd_as(fle->fe->fd, fd);
}
int recv_fd_from_peer(struct fdinfo_list_entry *fle)
{
struct fdinfo_list_entry *tmp;
- int fd, ret;
+ int fd, ret, tsock;
if (fle->received)
return fle->fe->fd;
+
+ tsock = get_service_fd(TRANSPORT_FD_OFF);
again:
- ret = recv_fds(fle->fe->fd, &fd, 1, NULL, (unsigned long *)&tmp);
+ ret = recv_fds(tsock, &fd, 1, NULL, (unsigned long *)&tmp);
if (ret)
return -1;
@@ -1000,7 +933,6 @@ int recv_fd_from_peer(struct fdinfo_list_entry *fle)
return -1;
goto again;
}
- close(fle->fe->fd);
BUG_ON(fle->received);
fle->received = true;
@@ -1014,11 +946,9 @@ int send_fd_to_peer(int fd, struct fdinfo_list_entry *fle)
sock = get_service_fd(TRANSPORT_FD_OFF);
- pr_info("\t\tWait fdinfo pid=%d fd=%d\n", fle->pid, fle->fe->fd);
- futex_wait_while(&fle->real_pid, 0);
+ pr_info("\t\tWait fdinfo pid=%d\n", fle->pid);
futex_wait_while(&pstree_item_by_virt(fle->pid)->transport_fd, 0);
- transport_name_gen(&saddr, &len,
- futex_get(&fle->real_pid), fle->fe->fd);
+ transport_name_gen(&saddr, &len, fle->pid, -1);
pr_info("\t\tSend fd %d to %s\n", fd, saddr.sun_path + 1);
return send_fds(sock, &saddr, len, &fd, 1, false, (unsigned long *)&fle);
}
@@ -1091,11 +1021,23 @@ static int serve_out_fd(int pid, int fd, struct file_desc *d)
return ret;
}
+static void maybe_want_recv_stage(int pid, struct fdinfo_list_entry *fle)
+{
+ struct fdinfo_list_entry *flem;
+
+ flem = file_master(fle->desc);
+
+ if (flem->pid != pid)
+ want_recv_stage();
+}
+
static int open_fd(int pid, struct fdinfo_list_entry *fle)
{
struct file_desc *d = fle->desc;
int new_fd;
+ maybe_want_recv_stage(pid, fle);
+
if (d->ops->post_open)
want_post_open_stage();
diff --git a/criu/include/files.h b/criu/include/files.h
index 41790ad..c5cde9e 100644
--- a/criu/include/files.h
+++ b/criu/include/files.h
@@ -70,7 +70,6 @@ struct fdinfo_list_entry {
struct list_head ps_list; /* To chain per-task files */
struct list_head used_list; /* To chain per-task used fds */
int pid;
- futex_t real_pid;
FdinfoEntry *fe;
bool received;
};
More information about the CRIU
mailing list