[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <A783F06F-A2CF-402D-BAAB-AFBCADD13307@fb.com>
Date: Wed, 16 Dec 2020 19:41:53 +0000
From: Song Liu <songliubraving@...com>
To: Yonghong Song <yhs@...com>
CC: bpf <bpf@...r.kernel.org>, Networking <netdev@...r.kernel.org>,
"ast@...nel.org" <ast@...nel.org>,
"daniel@...earbox.net" <daniel@...earbox.net>,
"andrii@...nel.org" <andrii@...nel.org>,
"john.fastabend@...il.com" <john.fastabend@...il.com>,
"kpsingh@...omium.org" <kpsingh@...omium.org>,
Kernel Team <Kernel-team@...com>
Subject: Re: [PATCH v2 bpf-next 1/4] bpf: introduce task_vma bpf_iter
> On Dec 16, 2020, at 9:36 AM, Yonghong Song <yhs@...com> wrote:
>
[...]
>> + if (info->task) {
>> + curr_task = info->task;
>> + } else {
>> + curr_task = task_seq_get_next(ns, &curr_tid, true);
>> + if (!curr_task) {
>> + info->task = NULL;
>> + info->tid++;
>
> Here, info->tid should be info->tid = curr_tid + 1.
> For exmaple, suppose initial curr_tid = info->tid = 10, and the
> above task_seq_get_next(...) returns NULL with curr_tid = 100
> which means tid = 100 has been visited. So we would like
> to set info->tid = 101 to avoid future potential redundant work.
> Returning NULL here will signal end of iteration but user
> space can still call read()...
Make sense. Let me fix.
>
>> + return NULL;
>> + }
>> +
>> + if (curr_tid != info->tid) {
>> + info->tid = curr_tid;
>> + new_task = true;
>> + }
>> +
>> + if (!curr_task->mm)
>> + goto next_task;
>> + info->task = curr_task;
>> + }
>> +
>> + mmap_read_lock(curr_task->mm);
>> + if (new_task) {
>> + vma = curr_task->mm->mmap;
>> + } else {
>> + /* We drop the lock between each iteration, so it is
>> + * necessary to use find_vma() to find the next vma. This
>> + * is similar to the mechanism in show_smaps_rollup().
>> + */
>> + vma = find_vma(curr_task->mm, info->vma.end - 1);
>> + /* same vma as previous iteration, use vma->next */
>> + if (vma && (vma->vm_start == info->vma.start))
>> + vma = vma->vm_next;
>
> We may have some issues here if control is returned to user space
> in the middle of iterations. For example,
> - seq_ops->next() sets info->vma properly (say corresponds to vma1 of tid1)
> - control returns to user space
> - control backs to kernel and this is not a new task since
> tid is the same
> - but we skipped this vma for show().
>
> I think the above skipping should be guarded. If the function
> is called from seq_ops->next(), yes it can be skipped.
> If the function is called from seq_ops->start(), it should not
> be skipped.
>
> Could you double check such a scenario with a smaller buffer
> size for read() in user space?
Yeah, this appeared to be a problem... Thanks for catching it! But I
am not sure (yet) how to fix it. Let me think more about it.
Thanks,
Song
Powered by blists - more mailing lists