[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20140430152344.GD28959@kvack.org>
Date: Wed, 30 Apr 2014 11:23:44 -0400
From: Benjamin LaHaise <bcrl@...ck.org>
To: Oleg Nesterov <oleg@...hat.com>
Cc: Andrew Morton <akpm@...ux-foundation.org>,
Kent Overstreet <kmo@...erainc.com>,
Al Viro <viro@...iv.linux.org.uk>, linux-aio@...ck.org,
linux-kernel@...r.kernel.org
Subject: Re: [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@...hat.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."
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists