* Re: [PATCH repost] ptr_ring: fix race conditions when resizing
[not found] <1487171217-6641-1-git-send-email-mst@redhat.com>
@ 2017-02-19 5:52 ` David Miller
2017-02-20 5:05 ` Michael S. Tsirkin
0 siblings, 1 reply; 4+ messages in thread
From: David Miller @ 2017-02-19 5:52 UTC (permalink / raw)
To: mst; +Cc: linux-kernel, dvyukov, stable, jasowang, netdev
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Sun, 19 Feb 2017 07:17:17 +0200
> Dave, could you merge this before 4.10? If not - I can try.
I just sent my last pull request to Linus, please merge it to
him directly.
Thanks.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH repost] ptr_ring: fix race conditions when resizing
2017-02-19 5:52 ` [PATCH repost] ptr_ring: fix race conditions when resizing David Miller
@ 2017-02-20 5:05 ` Michael S. Tsirkin
2017-02-20 16:24 ` David Miller
0 siblings, 1 reply; 4+ messages in thread
From: Michael S. Tsirkin @ 2017-02-20 5:05 UTC (permalink / raw)
To: David Miller; +Cc: linux-kernel, dvyukov, stable, jasowang, netdev
On Sun, Feb 19, 2017 at 12:52:48AM -0500, David Miller wrote:
> From: "Michael S. Tsirkin" <mst@redhat.com>
> Date: Sun, 19 Feb 2017 07:17:17 +0200
>
> > Dave, could you merge this before 4.10? If not - I can try.
>
> I just sent my last pull request to Linus, please merge it to
> him directly.
>
> Thanks.
I missed the opportunity. Could you pls queue the fix
for next release and copy stable?
--
MST
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH repost] ptr_ring: fix race conditions when resizing
2017-02-20 5:05 ` Michael S. Tsirkin
@ 2017-02-20 16:24 ` David Miller
0 siblings, 0 replies; 4+ messages in thread
From: David Miller @ 2017-02-20 16:24 UTC (permalink / raw)
To: mst; +Cc: linux-kernel, dvyukov, stable, jasowang, netdev
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Mon, 20 Feb 2017 07:05:35 +0200
> On Sun, Feb 19, 2017 at 12:52:48AM -0500, David Miller wrote:
>> From: "Michael S. Tsirkin" <mst@redhat.com>
>> Date: Sun, 19 Feb 2017 07:17:17 +0200
>>
>> > Dave, could you merge this before 4.10? If not - I can try.
>>
>> I just sent my last pull request to Linus, please merge it to
>> him directly.
>>
>> Thanks.
>
> I missed the opportunity. Could you pls queue the fix
> for next release and copy stable?
Ok, done.
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH repost] ptr_ring: fix race conditions when resizing
@ 2017-02-19 5:17 Michael S. Tsirkin
0 siblings, 0 replies; 4+ messages in thread
From: Michael S. Tsirkin @ 2017-02-19 5:17 UTC (permalink / raw)
To: linux-kernel; +Cc: Dmitry Vyukov, stable, David S. Miller, Jason Wang, netdev
Resizing currently drops consumer lock. This can cause entries to be
reordered, which isn't good in itself. More importantly, consumer can
detect a false ring empty condition and block forever.
Further, nesting of consumer within producer lock is problematic for
tun, since it produces entries in a BH, which causes a lock order
reversal:
CPU0 CPU1
---- ----
consume:
lock(&(&r->consumer_lock)->rlock);
resize:
local_irq_disable();
lock(&(&r->producer_lock)->rlock);
lock(&(&r->consumer_lock)->rlock);
<Interrupt>
produce:
lock(&(&r->producer_lock)->rlock);
To fix, nest producer lock within consumer lock during resize,
and keep consumer lock during the whole swap operation.
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Cc: stable@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
Dave, could you merge this before 4.10? If not - I can try.
include/linux/ptr_ring.h | 36 +++++++++++++++++++++++++++++++-----
1 file changed, 31 insertions(+), 5 deletions(-)
diff --git a/include/linux/ptr_ring.h b/include/linux/ptr_ring.h
index 2052011..6c70444 100644
--- a/include/linux/ptr_ring.h
+++ b/include/linux/ptr_ring.h
@@ -111,6 +111,11 @@ static inline int __ptr_ring_produce(struct ptr_ring *r, void *ptr)
return 0;
}
+/*
+ * Note: resize (below) nests producer lock within consumer lock, so if you
+ * consume in interrupt or BH context, you must disable interrupts/BH when
+ * calling this.
+ */
static inline int ptr_ring_produce(struct ptr_ring *r, void *ptr)
{
int ret;
@@ -242,6 +247,11 @@ static inline void *__ptr_ring_consume(struct ptr_ring *r)
return ptr;
}
+/*
+ * Note: resize (below) nests producer lock within consumer lock, so if you
+ * call this in interrupt or BH context, you must disable interrupts/BH when
+ * producing.
+ */
static inline void *ptr_ring_consume(struct ptr_ring *r)
{
void *ptr;
@@ -357,7 +367,7 @@ static inline void **__ptr_ring_swap_queue(struct ptr_ring *r, void **queue,
void **old;
void *ptr;
- while ((ptr = ptr_ring_consume(r)))
+ while ((ptr = __ptr_ring_consume(r)))
if (producer < size)
queue[producer++] = ptr;
else if (destroy)
@@ -372,6 +382,12 @@ static inline void **__ptr_ring_swap_queue(struct ptr_ring *r, void **queue,
return old;
}
+/*
+ * Note: producer lock is nested within consumer lock, so if you
+ * resize you must make sure all uses nest correctly.
+ * In particular if you consume ring in interrupt or BH context, you must
+ * disable interrupts/BH when doing so.
+ */
static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
void (*destroy)(void *))
{
@@ -382,17 +398,25 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
if (!queue)
return -ENOMEM;
- spin_lock_irqsave(&(r)->producer_lock, flags);
+ spin_lock_irqsave(&(r)->consumer_lock, flags);
+ spin_lock(&(r)->producer_lock);
old = __ptr_ring_swap_queue(r, queue, size, gfp, destroy);
- spin_unlock_irqrestore(&(r)->producer_lock, flags);
+ spin_unlock(&(r)->producer_lock);
+ spin_unlock_irqrestore(&(r)->consumer_lock, flags);
kfree(old);
return 0;
}
+/*
+ * Note: producer lock is nested within consumer lock, so if you
+ * resize you must make sure all uses nest correctly.
+ * In particular if you consume ring in interrupt or BH context, you must
+ * disable interrupts/BH when doing so.
+ */
static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings,
int size,
gfp_t gfp, void (*destroy)(void *))
@@ -412,10 +436,12 @@ static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings,
}
for (i = 0; i < nrings; ++i) {
- spin_lock_irqsave(&(rings[i])->producer_lock, flags);
+ spin_lock_irqsave(&(rings[i])->consumer_lock, flags);
+ spin_lock(&(rings[i])->producer_lock);
queues[i] = __ptr_ring_swap_queue(rings[i], queues[i],
size, gfp, destroy);
- spin_unlock_irqrestore(&(rings[i])->producer_lock, flags);
+ spin_unlock(&(rings[i])->producer_lock);
+ spin_unlock_irqrestore(&(rings[i])->consumer_lock, flags);
}
for (i = 0; i < nrings; ++i)
--
MST
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2017-02-20 16:24 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1487171217-6641-1-git-send-email-mst@redhat.com>
2017-02-19 5:52 ` [PATCH repost] ptr_ring: fix race conditions when resizing David Miller
2017-02-20 5:05 ` Michael S. Tsirkin
2017-02-20 16:24 ` David Miller
2017-02-19 5:17 Michael S. Tsirkin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).