Commit 692674b4 authored by Kirill Tkhai's avatar Kirill Tkhai Committed by Pavel Emelyanov

files: Make sending fds to peers async

Don't wait for "prepare" stage of every peer's fd. Just
send everything to a peer's global transport socket, and
the peer will find appropriate fd, it needs at the moment.

travis-ci: success for Rework file opening scheme to make it asynchronous (rev5)
Signed-off-by: 's avatarKirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent a288f3f2
......@@ -869,20 +869,17 @@ 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,},
{ "receive", receive_fd, true,},
{ "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_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)
......@@ -893,68 +890,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 task_fle(struct pstree_item *task, struct fdinfo_list_entry *fle)
{
struct fdinfo_list_entry *tmp;
......@@ -969,22 +904,20 @@ static int keep_fd_for_future(struct fdinfo_list_entry *fle, int fd)
{
BUG_ON(fle->received);
fle->received = 1;
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, (void *)&tmp, sizeof(struct fdinfo_list_entry *));
ret = recv_fds(tsock, &fd, 1, (void *)&tmp, sizeof(struct fdinfo_list_entry *));
if (ret)
return -1;
......@@ -998,7 +931,6 @@ again:
return -1;
goto again;
}
close(fle->fe->fd);
fle->received = 1;
return fd;
......@@ -1011,10 +943,7 @@ 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);
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, (void *)&fle, sizeof(struct fdinfo_list_entry *));
}
......
......@@ -70,14 +70,12 @@ 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;
u8 received:1;
};
static inline void fle_init(struct fdinfo_list_entry *fle, int pid, FdinfoEntry *fe)
{
futex_init(&fle->real_pid);
fle->pid = pid;
fle->fe = fe;
fle->received = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment