lkml.org 
[lkml]   [2014]   [Apr]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH v2 1/2] aio: change exit_aio() to load mm->ioctx_table once and avoid rcu_read_lock()
Hi Oleg,

On Wed, Apr 30, 2014 at 04:16:16PM +0200, Oleg Nesterov wrote:
> 1. We can read ->ioctx_table only once and we do not read rcu_read_lock()
> or even rcu_dereference().
>
> This mm has no users, nobody else can play with ->ioctx_table. Otherwise
> the code is buggy anyway, if we need rcu_read_lock() in a loop because
> ->ioctx_table can be updated then kfree(table) is obviously wrong.
>
> 2. Update the comment. "exit_mmap(mm) is coming" is the good reason to avoid
> munmap(), but another reason is that we simply can't do vm_munmap() unless
> current->mm == mm and this is not true in general, the caller is mmput().
>
> 3. We do not really need to nullify mm->ioctx_table before return, probably
> the current code does this to catch the potential problems. But in this
> case RCU_INIT_POINTER(NULL) looks better.

Looks pretty good. One minor style comment below.

> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
> ---
> fs/aio.c | 47 ++++++++++++++++++-----------------------------
> 1 files changed, 18 insertions(+), 29 deletions(-)
>
> diff --git a/fs/aio.c b/fs/aio.c
> index 79b7e69..3526c2b 100644
> --- a/fs/aio.c
> +++ b/fs/aio.c
> @@ -791,40 +791,29 @@ EXPORT_SYMBOL(wait_on_sync_kiocb);
> */
> void exit_aio(struct mm_struct *mm)
> {
> - struct kioctx_table *table;
> - struct kioctx *ctx;
> - unsigned i = 0;
> -
> - while (1) {
> - rcu_read_lock();
> - table = rcu_dereference(mm->ioctx_table);
> -
> - do {
> - if (!table || i >= table->nr) {
> - rcu_read_unlock();
> - rcu_assign_pointer(mm->ioctx_table, NULL);
> - if (table)
> - kfree(table);
> - return;
> - }
> -
> - ctx = table->table[i++];
> - } while (!ctx);
> + struct kioctx_table *table = rcu_dereference_raw(mm->ioctx_table);
> + int i;
>
> - rcu_read_unlock();
> + if (!table)
> + return;
>
> + for (i = 0; i < table->nr; ++i) {
> + struct kioctx *ctx = table->table[i];
> /*
> - * We don't need to bother with munmap() here -
> - * exit_mmap(mm) is coming and it'll unmap everything.
> - * Since aio_free_ring() uses non-zero ->mmap_size
> - * as indicator that it needs to unmap the area,
> - * just set it to 0; aio_free_ring() is the only
> - * place that uses ->mmap_size, so it's safe.
> + * We don't need to bother with munmap() here - exit_mmap(mm)
> + * is coming and it'll unmap everything. And we simply can't,
> + * this is not necessarily our ->mm.
> + * Since kill_ioctx() uses non-zero ->mmap_size as indicator
> + * that it needs to unmap the area, just set it to 0.
> */
> - ctx->mmap_size = 0;
> -
> - kill_ioctx(mm, ctx, NULL);
> + if (ctx) {
> + ctx->mmap_size = 0;
> + kill_ioctx(mm, ctx, NULL);
> + }

Rather than indenting and moving the two lines changing mmap_size and the
kill_ioctx() call, why not just do "if (!ctx) ... continue;"? That reduces
the number of lines changed and avoid excessive indentation.

-ben

> }
> +
> + RCU_INIT_POINTER(mm->ioctx_table, NULL);
> + kfree(table);
> }
>
> static void put_reqs_available(struct kioctx *ctx, unsigned nr)
> --
> 1.5.5.1
>

--
"Thought is the essence of where you are now."


\
 
 \ /
  Last update: 2014-04-30 18:21    [W:0.060 / U:0.228 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site