Skip to content

Commit

Permalink
bpf: Avoid iterating duplicated files for task_file iterator
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Yonghong Song <[email protected]>
Signed-off-by: Daniel Borkmann <[email protected]>
Reviewed-by: Josef Bacik <[email protected]>
Link: https://lore.kernel.org/bpf/[email protected]
  • Loading branch information
yonghong-song authored and borkmann committed Sep 2, 2020
1 parent 0697fec commit 203d7b0
Showing 1 changed file with 11 additions and 4 deletions.
15 changes: 11 additions & 4 deletions kernel/bpf/task_iter.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ struct bpf_iter_seq_task_info {
};

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 pid *pid;
Expand All @@ -36,6 +37,12 @@ static struct task_struct *task_seq_get_next(struct pid_namespace *ns,
if (!task) {
++*tid;
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();
Expand All @@ -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 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)
return NULL;

Expand All @@ -65,7 +72,7 @@ static void *task_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++*pos;
++info->tid;
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)
return NULL;

Expand Down Expand Up @@ -148,7 +155,7 @@ task_file_seq_get_next(struct bpf_iter_seq_task_file_info *info,
curr_files = *fstruct;
curr_fd = info->fd;
} else {
curr_task = task_seq_get_next(ns, &curr_tid);
curr_task = task_seq_get_next(ns, &curr_tid, true);
if (!curr_task)
return NULL;

Expand Down

0 comments on commit 203d7b0

Please sign in to comment.