Commit 22d61b88 authored by Pavel Emelyanov's avatar Pavel Emelyanov

files: Don't perform fd rst stages, if they will be no-op

The recv-fd stage is only required if we created any transport fd.
The post-open one is only required if there's at least one fdtype
with post-open callback in ops.

Both things can be evaluated in advance and unneeded stages can
be skipped.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent fcb6ee66
...@@ -550,6 +550,36 @@ err: ...@@ -550,6 +550,36 @@ err:
return -1; return -1;
} }
struct fd_open_state {
char *name;
int (*cb)(int, struct fdinfo_list_entry *);
/*
* Two last stages -- receive fds and post-open them -- are
* not required always. E.g. if no fd sharing takes place
* or task doens't have any files that need to be post-opened.
*
* Thus, in order not to scan through fdinfo-s lists in vain
* and speed things up a little bit, we may want to skeep these.
*/
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)
static void transport_name_gen(struct sockaddr_un *addr, int *len, static void transport_name_gen(struct sockaddr_un *addr, int *len,
int pid, int fd) int pid, int fd)
{ {
...@@ -613,6 +643,7 @@ static int open_transport_fd(int pid, struct fdinfo_list_entry *fle) ...@@ -613,6 +643,7 @@ static int open_transport_fd(int pid, struct fdinfo_list_entry *fle)
pr_info("\t\tWake up fdinfo pid=%d fd=%d\n", fle->pid, fle->fe->fd); pr_info("\t\tWake up fdinfo pid=%d fd=%d\n", fle->pid, fle->fe->fd);
futex_set_and_wake(&fle->real_pid, getpid()); futex_set_and_wake(&fle->real_pid, getpid());
want_recv_stage();
return 0; return 0;
} }
...@@ -705,6 +736,9 @@ static int open_fd(int pid, struct fdinfo_list_entry *fle) ...@@ -705,6 +736,9 @@ static int open_fd(int pid, struct fdinfo_list_entry *fle)
struct file_desc *d = fle->desc; struct file_desc *d = fle->desc;
int new_fd; int new_fd;
if (d->ops->post_open)
want_post_open_stage();
if (fle != file_master(d)) if (fle != file_master(d))
return 0; return 0;
...@@ -752,18 +786,6 @@ static int receive_fd(int pid, struct fdinfo_list_entry *fle) ...@@ -752,18 +786,6 @@ static int receive_fd(int pid, struct fdinfo_list_entry *fle)
return 0; return 0;
} }
struct fd_open_state {
char *name;
int (*cb)(int, struct fdinfo_list_entry *);
};
static struct fd_open_state states[] = {
{ "prepare", open_transport_fd, },
{ "create", open_fd, },
{ "receive", receive_fd, },
{ "post_create", post_open_fd, },
};
static int open_fdinfo(int pid, struct fdinfo_list_entry *fle, int state) static int open_fdinfo(int pid, struct fdinfo_list_entry *fle, int state)
{ {
pr_info("\tRestoring fd %d (state -> %s)\n", pr_info("\tRestoring fd %d (state -> %s)\n",
...@@ -841,6 +863,11 @@ int prepare_fds(struct pstree_item *me) ...@@ -841,6 +863,11 @@ int prepare_fds(struct pstree_item *me)
} }
for (state = 0; state < ARRAY_SIZE(states); state++) { for (state = 0; state < ARRAY_SIZE(states); state++) {
if (!states[state].required) {
pr_debug("Skipping %s fd stage\n", states[state].name);
continue;
}
ret = open_fdinfos(me->pid.virt, &me->rst->fds, state); ret = open_fdinfos(me->pid.virt, &me->rst->fds, state);
if (ret) if (ret)
break; break;
......
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