|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] blktap2: eliminate race from deferred work queue handling
# HG changeset patch
# User Jan Beulich <jbeulich@xxxxxxxx>
# Date 1471847043 -7200
# Mon Aug 22 08:24:03 2016 +0200
# Node ID 7ba8deb4c1be7d9353a88f2af0f23bf789d3f5d9
# Parent d8c979f0e04c5f5fa64001d4a2fa630117d5c76c
blktap2: eliminate race from deferred work queue handling
Clearing BLKTAP_DEFERRED together with splicing the queue onto a local
list is premature: blktap_defer() must not re-queue a tap before it got
removed from the list it's currently on (no matter whether that's the
global or local one), or else list corruption can occur. Effectively
the lock protects not only the global list (as its name suggests) but
also the list entries of all tap-s.
Effectively the BLKTAP_DEFERRED bit becomes pointless now: With the
changed locking we could as well check list_empty() in blktap_defer()
(of course requiring blktap_control_initialize_tap() to initialize the
entry).
Convert a bogus test_bit()/set_bit() pair to test_and_set_bit() at
once.
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
diff -r d8c979f0e04c -r 7ba8deb4c1be drivers/xen/blktap2/wait_queue.c
--- a/drivers/xen/blktap2/wait_queue.c Mon Aug 22 08:22:45 2016 +0200
+++ b/drivers/xen/blktap2/wait_queue.c Mon Aug 22 08:24:03 2016 +0200
@@ -15,13 +15,14 @@ blktap_run_deferred(void)
spin_lock_irqsave(&deferred_work_lock, flags);
list_splice_init(&deferred_work_queue, &queue);
- list_for_each_entry(tap, &queue, deferred_queue)
- clear_bit(BLKTAP_DEFERRED, &tap->dev_inuse);
spin_unlock_irqrestore(&deferred_work_lock, flags);
while (!list_empty(&queue)) {
tap = list_entry(queue.next, struct blktap, deferred_queue);
+ spin_lock_irqsave(&deferred_work_lock, flags);
+ clear_bit(BLKTAP_DEFERRED, &tap->dev_inuse);
list_del_init(&tap->deferred_queue);
+ spin_unlock_irqrestore(&deferred_work_lock, flags);
blktap_device_restart(tap);
}
}
@@ -32,9 +33,7 @@ blktap_defer(struct blktap *tap)
unsigned long flags;
spin_lock_irqsave(&deferred_work_lock, flags);
- if (!test_bit(BLKTAP_DEFERRED, &tap->dev_inuse)) {
- set_bit(BLKTAP_DEFERRED, &tap->dev_inuse);
+ if (!test_and_set_bit(BLKTAP_DEFERRED, &tap->dev_inuse))
list_add_tail(&tap->deferred_queue, &deferred_work_queue);
- }
spin_unlock_irqrestore(&deferred_work_lock, flags);
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |