From: Andrea Arcangeli <aarcange@redhat.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: linux-kernel@vger.kernel.org, Chris Mason <clm@fb.com>,
Andrew Morton <akpm@linux-foundation.org>,
Davide Libenzi <davidel@xmailserver.org>
Subject: Re: [PATCH] eventfd: document lockless access in eventfd_poll
Date: Wed, 2 Mar 2016 23:07:46 +0100 [thread overview]
Message-ID: <20160302220746.GF4946@redhat.com> (raw)
In-Reply-To: <1456956118-7082-1-git-send-email-pbonzini@redhat.com>
On Wed, Mar 02, 2016 at 11:01:58PM +0100, Paolo Bonzini wrote:
> diff --git a/fs/eventfd.c b/fs/eventfd.c
> index 8d0c0df01854..dbbbe203f82b 100644
> --- a/fs/eventfd.c
> +++ b/fs/eventfd.c
> @@ -121,8 +121,46 @@ static unsigned int eventfd_poll(struct file *file, poll_table *wait)
> u64 count;
>
> poll_wait(file, &ctx->wqh, wait);
> - smp_rmb();
> - count = ctx->count;
> +
> + /*
> + * All writes to ctx->count occur within ctx->wqh.lock. This read
> + * can be done outside ctx->wqh.lock because we know that poll_wait
> + * takes that lock (through add_wait_queue) if our caller will sleep.
> + *
> + * The read _can_ therefore seep into add_wait_queue's critical
> + * section, but cannot move above it! add_wait_queue's spin_lock acts
> + * as an acquire barrier and ensures that the read be ordered properly
> + * against the writes. The following CAN happen and is safe:
> + *
> + * poll write
> + * ----------------- ------------
> + * lock ctx->wqh.lock (in poll_wait)
> + * count = ctx->count
> + * __add_wait_queue
> + * unlock ctx->wqh.lock
> + * lock ctx->qwh.lock
> + * ctx->count += n
> + * if (waitqueue_active)
> + * wake_up_locked_poll
> + * unlock ctx->qwh.lock
> + * eventfd_poll returns 0
> + *
> + * but the following, which would miss a wakeup, cannot happen:
> + *
> + * poll write
> + * ----------------- ------------
> + * count = ctx->count (INVALID!)
> + * lock ctx->qwh.lock
> + * ctx->count += n
> + * **waitqueue_active is false**
> + * **no wake_up_locked_poll!**
> + * unlock ctx->qwh.lock
> + * lock ctx->wqh.lock (in poll_wait)
> + * __add_wait_queue
> + * unlock ctx->wqh.lock
> + * eventfd_poll returns 0
> + */
> + count = READ_ONCE(ctx->count);
>
> if (count > 0)
> events |= POLLIN;
Reviewed-by: Andrea Arcangeli <aarcange@redhat.com>
prev parent reply other threads:[~2016-03-02 22:07 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-03-02 22:01 [PATCH] eventfd: document lockless access in eventfd_poll Paolo Bonzini
2016-03-02 22:07 ` Andrea Arcangeli [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160302220746.GF4946@redhat.com \
--to=aarcange@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=clm@fb.com \
--cc=davidel@xmailserver.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.