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:
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;
DIR *fd_dir;
......@@ -118,12 +118,13 @@ static int collect_fds(pid_t pid, int *fd, int *nr_fd)
if (!strcmp(de->d_name, ".."))
continue;
if (n > *nr_fd - 1)
if (n > PARASITE_MAX_FDS - 1)
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("----------------------------------------\n");
......@@ -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,
int *fds, int nr_fds)
struct parasite_drain_fd *dfds)
{
int *lfds;
char *flags;
......@@ -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("----------------------------------------\n");
lfds = xmalloc(PARASITE_MAX_FDS * sizeof(int));
lfds = xmalloc(dfds->nr_fds * sizeof(int));
if (!lfds)
goto err;
flags = xmalloc(PARASITE_MAX_FDS * sizeof(char));
flags = xmalloc(dfds->nr_fds * sizeof(char));
if (!flags)
goto err1;
ret = parasite_drain_fds_seized(ctl, fds, lfds, nr_fds, flags);
ret = parasite_drain_fds_seized(ctl, dfds, lfds, flags);
if (ret)
goto err2;
for (i = 0; i < nr_fds; i++) {
ret = dump_one_file(ctl->pid, fds[i], lfds[i], flags[i], cr_fdset);
for (i = 0; i < dfds->nr_fds; i++) {
ret = dump_one_file(ctl->pid, dfds->fds[i], lfds[i], flags[i], cr_fdset);
close(lfds[i]);
if (ret)
goto err2;
......@@ -1346,16 +1347,14 @@ static int dump_one_task(struct pstree_item *item)
int ret = -1;
struct parasite_dump_misc misc;
struct cr_fdset *cr_fdset = NULL;
int nr_fds = PARASITE_MAX_FDS;
int *fds = NULL;
struct parasite_drain_fd *dfds;
pr_info("========================================\n");
pr_info("Dumping task (pid: %d)\n", pid);
pr_info("========================================\n");
fds = xmalloc(nr_fds * sizeof(int));
if (!fds)
dfds = xmalloc(sizeof(*dfds));
if (!dfds)
goto err_free;
if (item->state == TASK_STOPPED) {
......@@ -1387,7 +1386,7 @@ static int dump_one_task(struct pstree_item *item)
goto err;
}
ret = collect_fds(pid, fds, &nr_fds);
ret = collect_fds(pid, dfds);
if (ret) {
pr_err("Collect fds (pid: %d) failed with %d\n", pid, ret);
goto err;
......@@ -1415,7 +1414,7 @@ static int dump_one_task(struct pstree_item *item)
if (!cr_fdset)
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) {
pr_err("Dump files (pid: %d) failed with %d\n", pid, ret);
goto err_cure;
......@@ -1480,7 +1479,7 @@ err:
close_pid_proc();
err_free:
free_mappings(&vma_area_list);
xfree(fds);
xfree(dfds);
return ret;
err_cure:
......
......@@ -37,7 +37,9 @@ struct parasite_dump_tid_info;
extern int parasite_dump_thread_seized(struct parasite_ctl *ctl, pid_t pid,
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 struct parasite_ctl *parasite_infect_seized(pid_t pid,
......
......@@ -83,10 +83,15 @@ struct parasite_dump_tid_info {
#define PARASITE_MAX_FDS (PAGE_SIZE / sizeof(int))
struct parasite_drain_fd {
int fds[PARASITE_MAX_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
*/
......
......@@ -601,32 +601,25 @@ out:
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;
args = xmalloc(sizeof(*args));
if (!args)
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));
ret = parasite_execute(PARASITE_CMD_DRAIN_FDS, ctl,
dfds, drain_fds_size(dfds));
if (ret) {
pr_err("Parasite failed to drain descriptors\n");
goto err;
}
ret = recv_fds(ctl->tsock, lfds, nr_fds, flags);
ret = recv_fds(ctl->tsock, lfds, dfds->nr_fds, flags);
if (ret) {
pr_err("Can't retrieve FDs from socket\n");
goto err;
}
err:
xfree(args);
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