Commit ed397e3a authored by Pavel Emelyanov's avatar Pavel Emelyanov

fds: Optimize fds draning (mem + cpu)

* Don't dumplicate array when sending to parasite
* Allocate necessary space in cr-dump for local fds/flags
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent ab806ebc
...@@ -97,7 +97,7 @@ err: ...@@ -97,7 +97,7 @@ err:
struct cr_fdset *glob_fdset; struct cr_fdset *glob_fdset;
static int collect_fds(pid_t pid, int *fd, int *nr_fd) static int collect_fds(pid_t pid, struct parasite_drain_fd *dfds)
{ {
struct dirent *de; struct dirent *de;
DIR *fd_dir; DIR *fd_dir;
...@@ -118,12 +118,13 @@ static int collect_fds(pid_t pid, int *fd, int *nr_fd) ...@@ -118,12 +118,13 @@ static int collect_fds(pid_t pid, int *fd, int *nr_fd)
if (!strcmp(de->d_name, "..")) if (!strcmp(de->d_name, ".."))
continue; continue;
if (n > *nr_fd - 1) if (n > PARASITE_MAX_FDS - 1)
return -ENOMEM; return -ENOMEM;
fd[n++] = atoi(de->d_name);
dfds->fds[n++] = atoi(de->d_name);
} }
*nr_fd = n; dfds->nr_fds = n;
pr_info("Found %d file descriptors\n", n); pr_info("Found %d file descriptors\n", n);
pr_info("----------------------------------------\n"); pr_info("----------------------------------------\n");
...@@ -312,7 +313,7 @@ static int dump_one_file(pid_t pid, int fd, int lfd, char fd_flags, ...@@ -312,7 +313,7 @@ static int dump_one_file(pid_t pid, int fd, int lfd, char fd_flags,
} }
static int dump_task_files_seized(struct parasite_ctl *ctl, const struct cr_fdset *cr_fdset, static int dump_task_files_seized(struct parasite_ctl *ctl, const struct cr_fdset *cr_fdset,
int *fds, int nr_fds) struct parasite_drain_fd *dfds)
{ {
int *lfds; int *lfds;
char *flags; char *flags;
...@@ -322,20 +323,20 @@ static int dump_task_files_seized(struct parasite_ctl *ctl, const struct cr_fdse ...@@ -322,20 +323,20 @@ static int dump_task_files_seized(struct parasite_ctl *ctl, const struct cr_fdse
pr_info("Dumping opened files (pid: %d)\n", ctl->pid); pr_info("Dumping opened files (pid: %d)\n", ctl->pid);
pr_info("----------------------------------------\n"); pr_info("----------------------------------------\n");
lfds = xmalloc(PARASITE_MAX_FDS * sizeof(int)); lfds = xmalloc(dfds->nr_fds * sizeof(int));
if (!lfds) if (!lfds)
goto err; goto err;
flags = xmalloc(PARASITE_MAX_FDS * sizeof(char)); flags = xmalloc(dfds->nr_fds * sizeof(char));
if (!flags) if (!flags)
goto err1; goto err1;
ret = parasite_drain_fds_seized(ctl, fds, lfds, nr_fds, flags); ret = parasite_drain_fds_seized(ctl, dfds, lfds, flags);
if (ret) if (ret)
goto err2; goto err2;
for (i = 0; i < nr_fds; i++) { for (i = 0; i < dfds->nr_fds; i++) {
ret = dump_one_file(ctl->pid, fds[i], lfds[i], flags[i], cr_fdset); ret = dump_one_file(ctl->pid, dfds->fds[i], lfds[i], flags[i], cr_fdset);
close(lfds[i]); close(lfds[i]);
if (ret) if (ret)
goto err2; goto err2;
...@@ -1346,16 +1347,14 @@ static int dump_one_task(struct pstree_item *item) ...@@ -1346,16 +1347,14 @@ static int dump_one_task(struct pstree_item *item)
int ret = -1; int ret = -1;
struct parasite_dump_misc misc; struct parasite_dump_misc misc;
struct cr_fdset *cr_fdset = NULL; struct cr_fdset *cr_fdset = NULL;
struct parasite_drain_fd *dfds;
int nr_fds = PARASITE_MAX_FDS;
int *fds = NULL;
pr_info("========================================\n"); pr_info("========================================\n");
pr_info("Dumping task (pid: %d)\n", pid); pr_info("Dumping task (pid: %d)\n", pid);
pr_info("========================================\n"); pr_info("========================================\n");
fds = xmalloc(nr_fds * sizeof(int)); dfds = xmalloc(sizeof(*dfds));
if (!fds) if (!dfds)
goto err_free; goto err_free;
if (item->state == TASK_STOPPED) { if (item->state == TASK_STOPPED) {
...@@ -1387,7 +1386,7 @@ static int dump_one_task(struct pstree_item *item) ...@@ -1387,7 +1386,7 @@ static int dump_one_task(struct pstree_item *item)
goto err; goto err;
} }
ret = collect_fds(pid, fds, &nr_fds); ret = collect_fds(pid, dfds);
if (ret) { if (ret) {
pr_err("Collect fds (pid: %d) failed with %d\n", pid, ret); pr_err("Collect fds (pid: %d) failed with %d\n", pid, ret);
goto err; goto err;
...@@ -1415,7 +1414,7 @@ static int dump_one_task(struct pstree_item *item) ...@@ -1415,7 +1414,7 @@ static int dump_one_task(struct pstree_item *item)
if (!cr_fdset) if (!cr_fdset)
goto err_cure; goto err_cure;
ret = dump_task_files_seized(parasite_ctl, cr_fdset, fds, nr_fds); ret = dump_task_files_seized(parasite_ctl, cr_fdset, dfds);
if (ret) { if (ret) {
pr_err("Dump files (pid: %d) failed with %d\n", pid, ret); pr_err("Dump files (pid: %d) failed with %d\n", pid, ret);
goto err_cure; goto err_cure;
...@@ -1480,7 +1479,7 @@ err: ...@@ -1480,7 +1479,7 @@ err:
close_pid_proc(); close_pid_proc();
err_free: err_free:
free_mappings(&vma_area_list); free_mappings(&vma_area_list);
xfree(fds); xfree(dfds);
return ret; return ret;
err_cure: err_cure:
......
...@@ -37,7 +37,9 @@ struct parasite_dump_tid_info; ...@@ -37,7 +37,9 @@ struct parasite_dump_tid_info;
extern int parasite_dump_thread_seized(struct parasite_ctl *ctl, pid_t pid, extern int parasite_dump_thread_seized(struct parasite_ctl *ctl, pid_t pid,
unsigned int **tid_add, u32 *tid); unsigned int **tid_add, u32 *tid);
extern int parasite_drain_fds_seized(struct parasite_ctl *ctl, int *fds, int *lfds, int nr_fds, char *flags); struct parasite_drain_fd;
extern int parasite_drain_fds_seized(struct parasite_ctl *ctl, struct parasite_drain_fd *dfds,
int *lfds, char *flags);
extern int parasite_cure_seized(struct parasite_ctl *ctl); extern int parasite_cure_seized(struct parasite_ctl *ctl);
extern struct parasite_ctl *parasite_infect_seized(pid_t pid, extern struct parasite_ctl *parasite_infect_seized(pid_t pid,
......
...@@ -83,10 +83,15 @@ struct parasite_dump_tid_info { ...@@ -83,10 +83,15 @@ struct parasite_dump_tid_info {
#define PARASITE_MAX_FDS (PAGE_SIZE / sizeof(int)) #define PARASITE_MAX_FDS (PAGE_SIZE / sizeof(int))
struct parasite_drain_fd { struct parasite_drain_fd {
int fds[PARASITE_MAX_FDS]; int nr_fds;
int nr_fds; int fds[PARASITE_MAX_FDS];
}; };
static inline int drain_fds_size(struct parasite_drain_fd *dfds)
{
return sizeof(dfds->nr_fds) + dfds->nr_fds * sizeof(dfds->fds[0]);
}
/* /*
* Some useful offsets * Some useful offsets
*/ */
......
...@@ -601,32 +601,25 @@ out: ...@@ -601,32 +601,25 @@ out:
return ret; return ret;
} }
int parasite_drain_fds_seized(struct parasite_ctl *ctl, int *fds, int *lfds, int nr_fds, char *flags) int parasite_drain_fds_seized(struct parasite_ctl *ctl,
struct parasite_drain_fd *dfds, int *lfds, char *flags)
{ {
struct parasite_drain_fd *args;
int ret = -1; int ret = -1;
args = xmalloc(sizeof(*args)); ret = parasite_execute(PARASITE_CMD_DRAIN_FDS, ctl,
if (!args) dfds, drain_fds_size(dfds));
return -ENOMEM;
args->nr_fds = nr_fds;
memcpy(&args->fds, fds, sizeof(int) * nr_fds);
ret = parasite_execute(PARASITE_CMD_DRAIN_FDS, ctl, args, sizeof(*args));
if (ret) { if (ret) {
pr_err("Parasite failed to drain descriptors\n"); pr_err("Parasite failed to drain descriptors\n");
goto err; goto err;
} }
ret = recv_fds(ctl->tsock, lfds, nr_fds, flags); ret = recv_fds(ctl->tsock, lfds, dfds->nr_fds, flags);
if (ret) { if (ret) {
pr_err("Can't retrieve FDs from socket\n"); pr_err("Can't retrieve FDs from socket\n");
goto err; goto err;
} }
err: err:
xfree(args);
return ret; return ret;
} }
......
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