forked from luck/tmp_suning_uos_patched
bpf: Avoid iterating duplicated files for task_file iterator
Currently, task_file iterator iterates all files from all tasks. This may potentially visit a lot of duplicated files if there are many tasks sharing the same files, e.g., typical pthreads where these pthreads and the main thread are sharing the same files. This patch changed task_file iterator to skip a particular task if that task shares the same files as its group_leader (the task having the same tgid and also task->tgid == task->pid). This will preserve the same result, visiting all files from all tasks, and will reduce runtime cost significantl, e.g., if there are a lot of pthreads and the process has a lot of open files. Suggested-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Yonghong Song <yhs@fb.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Josef Bacik <josef@toxicpanda.com> Link: https://lore.kernel.org/bpf/20200902023112.1672792-1-yhs@fb.com
This commit is contained in:
parent
0697fecf7e
commit
203d7b054f
|
@ -22,7 +22,8 @@ struct bpf_iter_seq_task_info {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct task_struct *task_seq_get_next(struct pid_namespace *ns,
|
static struct task_struct *task_seq_get_next(struct pid_namespace *ns,
|
||||||
u32 *tid)
|
u32 *tid,
|
||||||
|
bool skip_if_dup_files)
|
||||||
{
|
{
|
||||||
struct task_struct *task = NULL;
|
struct task_struct *task = NULL;
|
||||||
struct pid *pid;
|
struct pid *pid;
|
||||||
|
@ -36,6 +37,12 @@ static struct task_struct *task_seq_get_next(struct pid_namespace *ns,
|
||||||
if (!task) {
|
if (!task) {
|
||||||
++*tid;
|
++*tid;
|
||||||
goto retry;
|
goto retry;
|
||||||
|
} else if (skip_if_dup_files && task->tgid != task->pid &&
|
||||||
|
task->files == task->group_leader->files) {
|
||||||
|
put_task_struct(task);
|
||||||
|
task = NULL;
|
||||||
|
++*tid;
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
@ -48,7 +55,7 @@ static void *task_seq_start(struct seq_file *seq, loff_t *pos)
|
||||||
struct bpf_iter_seq_task_info *info = seq->private;
|
struct bpf_iter_seq_task_info *info = seq->private;
|
||||||
struct task_struct *task;
|
struct task_struct *task;
|
||||||
|
|
||||||
task = task_seq_get_next(info->common.ns, &info->tid);
|
task = task_seq_get_next(info->common.ns, &info->tid, false);
|
||||||
if (!task)
|
if (!task)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -65,7 +72,7 @@ static void *task_seq_next(struct seq_file *seq, void *v, loff_t *pos)
|
||||||
++*pos;
|
++*pos;
|
||||||
++info->tid;
|
++info->tid;
|
||||||
put_task_struct((struct task_struct *)v);
|
put_task_struct((struct task_struct *)v);
|
||||||
task = task_seq_get_next(info->common.ns, &info->tid);
|
task = task_seq_get_next(info->common.ns, &info->tid, false);
|
||||||
if (!task)
|
if (!task)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -148,7 +155,7 @@ task_file_seq_get_next(struct bpf_iter_seq_task_file_info *info,
|
||||||
curr_files = *fstruct;
|
curr_files = *fstruct;
|
||||||
curr_fd = info->fd;
|
curr_fd = info->fd;
|
||||||
} else {
|
} else {
|
||||||
curr_task = task_seq_get_next(ns, &curr_tid);
|
curr_task = task_seq_get_next(ns, &curr_tid, true);
|
||||||
if (!curr_task)
|
if (!curr_task)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user