aboutsummaryrefslogtreecommitdiff
path: root/hw/block
diff options
context:
space:
mode:
authorAnthony PERARD <anthony.perard@citrix.com>2021-03-08 14:32:32 +0000
committerAnthony PERARD <anthony.perard@citrix.com>2021-03-23 11:18:20 +0000
commitb807ca3fa0ca29ec015adcf4045e716337cd3635 (patch)
treef9941aa8066a4425cdde935e6d1e70c569c7a28d /hw/block
parent5ca634afcf83215a9a54ca6e66032325b5ffb5f6 (diff)
downloadqemu-b807ca3fa0ca29ec015adcf4045e716337cd3635.zip
qemu-b807ca3fa0ca29ec015adcf4045e716337cd3635.tar.gz
qemu-b807ca3fa0ca29ec015adcf4045e716337cd3635.tar.bz2
xen-block: Fix removal of backend instance via xenstore
Whenever a Xen block device is detach via xenstore, the image associated with it remained open by the backend QEMU and an error is logged: qemu-system-i386: failed to destroy drive: Node xvdz-qcow2 is in use This happened since object_unparent() doesn't immediately frees the object and thus keep a reference to the node we are trying to free. The reference is hold by the "drive" property and the call xen_block_drive_destroy() fails. In order to fix that, we call drain_call_rcu() to run the callback setup by bus_remove_child() via object_unparent(). Fixes: 2d24a6466154 ("device-core: use RCU for list of children of a bus") Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Reviewed-by: Paul Durrant <paul@xen.org> Message-Id: <20210308143232.83388-1-anthony.perard@citrix.com>
Diffstat (limited to 'hw/block')
-rw-r--r--hw/block/xen-block.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
index ac82d54..83754a4 100644
--- a/hw/block/xen-block.c
+++ b/hw/block/xen-block.c
@@ -972,6 +972,15 @@ static void xen_block_device_destroy(XenBackendInstance *backend,
object_unparent(OBJECT(xendev));
+ /*
+ * Drain all pending RCU callbacks as object_unparent() frees `xendev'
+ * in a RCU callback.
+ * And due to the property "drive" still existing in `xendev', we
+ * can't destroy the XenBlockDrive associated with `xendev' with
+ * xen_block_drive_destroy() below.
+ */
+ drain_call_rcu();
+
if (iothread) {
xen_block_iothread_destroy(iothread, errp);
if (*errp) {