From: Al Viro <viro@ZenIV.linux.org.uk>
To: lkp@lists.01.org
Subject: Re: [PATCH 6/6] fs: replace f_ops->get_poll_head with a static ->f_poll_head pointer
Date: Thu, 28 Jun 2018 21:28:37 +0100 [thread overview]
Message-ID: <20180628202837.GI30522@ZenIV.linux.org.uk> (raw)
In-Reply-To: <CA+55aFyPUpd3tWVqbTVXGKjMb42+g-9MCfvjXLpb0RGSOW8sbA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 3277 bytes --]
On Thu, Jun 28, 2018 at 12:31:14PM -0700, Linus Torvalds wrote:
> > * a *LOT* of ->poll() instances only block in __pollwait()
> > called (indirectly) on the first pass.
>
> They are *all* supposed to do it.
Sure, but...
static __poll_t binder_poll(struct file *filp,
struct poll_table_struct *wait)
{
struct binder_proc *proc = filp->private_data;
struct binder_thread *thread = NULL;
bool wait_for_proc_work;
thread = binder_get_thread(proc);
if (!thread)
return POLLERR;
...
static struct binder_thread *binder_get_thread(struct binder_proc *proc)
{
struct binder_thread *thread;
struct binder_thread *new_thread;
binder_inner_proc_lock(proc);
thread = binder_get_thread_ilocked(proc, NULL);
binder_inner_proc_unlock(proc);
if (!thread) {
new_thread = kzalloc(sizeof(*thread), GFP_KERNEL);
And that's hardly unique - we have instances playing with timers,
allocations, whatnot. Even straight mutex_lock(), as in
static __poll_t i915_perf_poll(struct file *file, poll_table *wait)
{
struct i915_perf_stream *stream = file->private_data;
struct drm_i915_private *dev_priv = stream->dev_priv;
__poll_t ret;
mutex_lock(&dev_priv->perf.lock);
ret = i915_perf_poll_locked(dev_priv, stream, file, wait);
mutex_unlock(&dev_priv->perf.lock);
return ret;
}
or
static __poll_t cec_poll(struct file *filp,
struct poll_table_struct *poll)
{
struct cec_fh *fh = filp->private_data;
struct cec_adapter *adap = fh->adap;
__poll_t res = 0;
if (!cec_is_registered(adap))
return EPOLLERR | EPOLLHUP;
mutex_lock(&adap->lock);
if (adap->is_configured &&
adap->transmit_queue_sz < CEC_MAX_MSG_TX_QUEUE_SZ)
res |= EPOLLOUT | EPOLLWRNORM;
if (fh->queued_msgs)
res |= EPOLLIN | EPOLLRDNORM;
if (fh->total_queued_events)
res |= EPOLLPRI;
poll_wait(filp, &fh->wait, poll);
mutex_unlock(&adap->lock);
return res;
}
etc.
>
> The whole idea with "->poll()" is that the model of operation is:
>
> - add_wait_queue() and return state on the first pass
>
> - on subsequent passes (or if somebody else already returned a state
> that means we already know we're not going to wait), the poll table is
> NULL, so you *CANNOT* add_wait_queue again, so you just return state.
>
> Additionally, once _anybody_ has returned a "I already have the
> event", we also clear the poll table queue, so subsequent accesses
> will purely be for returning the poll state.
>
> So I don't understand why you're asking for annotation. The whole "you
> add yourself to the poll table" is *fundamentally* only done on the
> first pass. You should never do it for later passes.
Sure. Unfortunately, adding yourself to the poll table is not the only
way to block. And a plenty of instances in e.g. drivers/media (where
the bulk of ->poll() instances lives) are very free with grabbing mutexes
as they go.
WARNING: multiple messages have this Message-ID (diff)
From: Al Viro <viro@ZenIV.linux.org.uk>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Christoph Hellwig <hch@lst.de>,
linux-fsdevel <linux-fsdevel@vger.kernel.org>,
Network Development <netdev@vger.kernel.org>, LKP <lkp@01.org>
Subject: Re: [PATCH 6/6] fs: replace f_ops->get_poll_head with a static ->f_poll_head pointer
Date: Thu, 28 Jun 2018 21:28:37 +0100 [thread overview]
Message-ID: <20180628202837.GI30522@ZenIV.linux.org.uk> (raw)
In-Reply-To: <CA+55aFyPUpd3tWVqbTVXGKjMb42+g-9MCfvjXLpb0RGSOW8sbA@mail.gmail.com>
On Thu, Jun 28, 2018 at 12:31:14PM -0700, Linus Torvalds wrote:
> > * a *LOT* of ->poll() instances only block in __pollwait()
> > called (indirectly) on the first pass.
>
> They are *all* supposed to do it.
Sure, but...
static __poll_t binder_poll(struct file *filp,
struct poll_table_struct *wait)
{
struct binder_proc *proc = filp->private_data;
struct binder_thread *thread = NULL;
bool wait_for_proc_work;
thread = binder_get_thread(proc);
if (!thread)
return POLLERR;
...
static struct binder_thread *binder_get_thread(struct binder_proc *proc)
{
struct binder_thread *thread;
struct binder_thread *new_thread;
binder_inner_proc_lock(proc);
thread = binder_get_thread_ilocked(proc, NULL);
binder_inner_proc_unlock(proc);
if (!thread) {
new_thread = kzalloc(sizeof(*thread), GFP_KERNEL);
And that's hardly unique - we have instances playing with timers,
allocations, whatnot. Even straight mutex_lock(), as in
static __poll_t i915_perf_poll(struct file *file, poll_table *wait)
{
struct i915_perf_stream *stream = file->private_data;
struct drm_i915_private *dev_priv = stream->dev_priv;
__poll_t ret;
mutex_lock(&dev_priv->perf.lock);
ret = i915_perf_poll_locked(dev_priv, stream, file, wait);
mutex_unlock(&dev_priv->perf.lock);
return ret;
}
or
static __poll_t cec_poll(struct file *filp,
struct poll_table_struct *poll)
{
struct cec_fh *fh = filp->private_data;
struct cec_adapter *adap = fh->adap;
__poll_t res = 0;
if (!cec_is_registered(adap))
return EPOLLERR | EPOLLHUP;
mutex_lock(&adap->lock);
if (adap->is_configured &&
adap->transmit_queue_sz < CEC_MAX_MSG_TX_QUEUE_SZ)
res |= EPOLLOUT | EPOLLWRNORM;
if (fh->queued_msgs)
res |= EPOLLIN | EPOLLRDNORM;
if (fh->total_queued_events)
res |= EPOLLPRI;
poll_wait(filp, &fh->wait, poll);
mutex_unlock(&adap->lock);
return res;
}
etc.
>
> The whole idea with "->poll()" is that the model of operation is:
>
> - add_wait_queue() and return state on the first pass
>
> - on subsequent passes (or if somebody else already returned a state
> that means we already know we're not going to wait), the poll table is
> NULL, so you *CANNOT* add_wait_queue again, so you just return state.
>
> Additionally, once _anybody_ has returned a "I already have the
> event", we also clear the poll table queue, so subsequent accesses
> will purely be for returning the poll state.
>
> So I don't understand why you're asking for annotation. The whole "you
> add yourself to the poll table" is *fundamentally* only done on the
> first pass. You should never do it for later passes.
Sure. Unfortunately, adding yourself to the poll table is not the only
way to block. And a plenty of instances in e.g. drivers/media (where
the bulk of ->poll() instances lives) are very free with grabbing mutexes
as they go.
next prev parent reply other threads:[~2018-06-28 20:28 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-28 14:20 [RFC] replace ->get_poll_head with a waitqueue pointer in struct file Christoph Hellwig
2018-06-28 14:20 ` Christoph Hellwig
2018-06-28 14:20 ` [PATCH 1/6] net: remove sock_poll_busy_flag Christoph Hellwig
2018-06-28 14:20 ` Christoph Hellwig
2018-06-28 14:20 ` [PATCH 2/6] net: remove bogus RCU annotations on socket.wq Christoph Hellwig
2018-06-28 14:20 ` Christoph Hellwig
2018-06-28 14:20 ` [PATCH 3/6] net: don't detour through struct to find the poll head Christoph Hellwig
2018-06-28 14:20 ` Christoph Hellwig
2018-06-28 14:20 ` [PATCH 4/6] net: remove busy polling from sock_get_poll_head Christoph Hellwig
2018-06-28 14:20 ` Christoph Hellwig
2018-06-28 14:20 ` [PATCH 5/6] net: remove sock_poll_busy_loop Christoph Hellwig
2018-06-28 14:20 ` Christoph Hellwig
2018-06-28 14:20 ` [PATCH 6/6] fs: replace f_ops->get_poll_head with a static ->f_poll_head pointer Christoph Hellwig
2018-06-28 14:20 ` Christoph Hellwig
2018-06-28 16:40 ` Linus Torvalds
2018-06-28 16:40 ` Linus Torvalds
2018-06-28 18:17 ` Al Viro
2018-06-28 18:17 ` Al Viro
2018-06-28 19:31 ` Linus Torvalds
2018-06-28 19:31 ` Linus Torvalds
2018-06-28 20:28 ` Al Viro [this message]
2018-06-28 20:28 ` Al Viro
2018-06-28 20:37 ` Al Viro
2018-06-28 20:37 ` Al Viro
2018-06-28 21:16 ` Linus Torvalds
2018-06-28 21:16 ` Linus Torvalds
2018-06-28 21:11 ` Linus Torvalds
2018-06-28 21:11 ` Linus Torvalds
2018-06-28 21:30 ` Al Viro
2018-06-28 21:30 ` Al Viro
2018-06-28 21:39 ` Linus Torvalds
2018-06-28 21:39 ` Linus Torvalds
2018-06-28 22:20 ` Al Viro
2018-06-28 22:20 ` Al Viro
2018-06-28 22:35 ` Linus Torvalds
2018-06-28 22:35 ` Linus Torvalds
2018-06-28 22:49 ` Al Viro
2018-06-28 22:49 ` Al Viro
2018-06-28 22:55 ` Linus Torvalds
2018-06-28 22:55 ` Linus Torvalds
2018-06-28 23:37 ` Al Viro
2018-06-28 23:37 ` Al Viro
2018-06-29 0:13 ` Linus Torvalds
2018-06-29 0:13 ` Linus Torvalds
2018-06-29 13:29 ` Christoph Hellwig
2018-06-29 13:29 ` Christoph Hellwig
2018-06-29 13:40 ` Linus Torvalds
2018-06-29 13:40 ` Linus Torvalds
2018-06-29 13:28 ` Christoph Hellwig
2018-06-29 13:28 ` Christoph Hellwig
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=20180628202837.GI30522@ZenIV.linux.org.uk \
--to=viro@zeniv.linux.org.uk \
--cc=lkp@lists.01.org \
/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.