On Mon, Jul 25, 2022 at 10:17:11PM -0700, Kui-Feng Lee wrote: > Allow creating an iterator that loops through resources of one task/thread. > > People could only create iterators to loop through all resources of > files, vma, and tasks in the system, even though they were interested > in only the resources of a specific task or process. Passing the > additional parameters, people can now create an iterator to go > through all resources or only the resources of a task. > > Signed-off-by: Kui-Feng Lee <kuifeng@xxxxxx> > --- > include/linux/bpf.h | 4 ++ > include/uapi/linux/bpf.h | 23 ++++++++++ > kernel/bpf/task_iter.c | 81 +++++++++++++++++++++++++--------- > tools/include/uapi/linux/bpf.h | 23 ++++++++++ > 4 files changed, 109 insertions(+), 22 deletions(-) > > diff --git a/include/linux/bpf.h b/include/linux/bpf.h > index 11950029284f..c8d164404e20 100644 > --- a/include/linux/bpf.h > +++ b/include/linux/bpf.h > @@ -1718,6 +1718,10 @@ int bpf_obj_get_user(const char __user *pathname, int flags); > > struct bpf_iter_aux_info { > struct bpf_map *map; > + struct { > + __u32 tid; should be just u32 ? > + u8 type; > + } task; > }; > SNIP > > /* BPF syscall commands, see bpf(2) man-page for more details. */ > diff --git a/kernel/bpf/task_iter.c b/kernel/bpf/task_iter.c > index 8c921799def4..7979aacb651e 100644 > --- a/kernel/bpf/task_iter.c > +++ b/kernel/bpf/task_iter.c > @@ -12,6 +12,8 @@ > > struct bpf_iter_seq_task_common { > struct pid_namespace *ns; > + u32 tid; > + u8 type; > }; > > struct bpf_iter_seq_task_info { > @@ -22,18 +24,31 @@ struct bpf_iter_seq_task_info { > u32 tid; > }; > > -static struct task_struct *task_seq_get_next(struct pid_namespace *ns, > +static struct task_struct *task_seq_get_next(struct bpf_iter_seq_task_common *common, > u32 *tid, > bool skip_if_dup_files) > { > struct task_struct *task = NULL; > struct pid *pid; > > + if (common->type == BPF_TASK_ITER_TID) { > + if (*tid) > + return NULL; I tested and this condition breaks it for fd iterations, not sure about the task and vma, because they share this function if bpf_seq_read is called with small buffer there will be multiple calls to task_file_seq_get_next and second one will stop in here, even if there are more files to be displayed for the task in filter it'd be nice to have some test for this ;-) or perhaps compare with the not filtered output SNIP > static const struct seq_operations task_seq_ops = { > .start = task_seq_start, > .next = task_seq_next, > @@ -137,8 +166,7 @@ struct bpf_iter_seq_task_file_info { > static struct file * > task_file_seq_get_next(struct bpf_iter_seq_task_file_info *info) > { > - struct pid_namespace *ns = info->common.ns; > - u32 curr_tid = info->tid; > + u32 saved_tid = info->tid; > struct task_struct *curr_task; > unsigned int curr_fd = info->fd; > > @@ -151,21 +179,18 @@ task_file_seq_get_next(struct bpf_iter_seq_task_file_info *info) > curr_task = info->task; > curr_fd = info->fd; > } else { > - curr_task = task_seq_get_next(ns, &curr_tid, true); > + curr_task = task_seq_get_next(&info->common, &info->tid, true); > if (!curr_task) { > info->task = NULL; > - info->tid = curr_tid; > return NULL; > } nit, looks like we're missing proper indent in here > > - /* set info->task and info->tid */ > + /* set info->task */ > info->task = curr_task; > - if (curr_tid == info->tid) { > + if (saved_tid == info->tid) > curr_fd = info->fd; > - } else { > - info->tid = curr_tid; > + else SNIP