From 95687dc61d2d7ccc0aea95861bdb43165f4fa4e7 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 26 Jan 2011 14:58:05 -0200 Subject: [RHEL6 qemu-kvm PATCH 10/14] Implement drive_del to decouple block removal from device removal (v2) RH-Author: Anthony Liguori Message-id: <1296053886-2905-11-git-send-email-aliguori@redhat.com> Patchwork-id: 17097 O-Subject: [PATCH RHEL6.1 qemu-kvm 10/11] Implement drive_del to decouple block removal from device removal (v2) Bugzilla: 654682 RH-Acked-by: Kevin Wolf RH-Acked-by: Marcelo Tosatti RH-Acked-by: Markus Armbruster From: Ryan Harper BZ: 654682 Upstream-status: accepted Currently device hotplug removal code is tied to device removal via ACPI. All pci devices that are removable via device_del() require the guest to respond to the request. In some cases the guest may not respond leaving the device still accessible to the guest. The management layer doesn't currently have a reliable way to revoke access to host resource in the presence of an uncooperative guest. This patch implements a new monitor command, drive_del, which provides an explicit command to revoke access to a host block device. drive_del first quiesces the block device (qemu_aio_flush; bdrv_flush() and bdrv_close()). This prevents further IO from being submitted against the host device. Finally, drive_del cleans up pointers between the drive object (host resource) and the device object (guest resource). Signed-off-by: Ryan Harper Signed-off-by: Kevin Wolf (cherry picked from commit 9063f81415f3518ef8206e74085c2a92c96890a0) Since upstream does not expose a drive_del QMP command, put this command under the __com.redhat namespace. Signed-off-by: Anthony Liguori -- v1 -> v2 - Remove trailing whitespace - Change drive_get_by_id to drive_get_by_blockdev to match upstream Signed-off-by: Eduardo Habkost --- hw/device-hotplug.c | 37 +++++++++++++++++++++++++++++++++++++ qemu-monitor.hx | 39 +++++++++++++++++++++++++++++++++++++++ sysemu.h | 1 + 3 files changed, 77 insertions(+), 0 deletions(-) diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c index 3b957b2..16d7950 100644 --- a/hw/device-hotplug.c +++ b/hw/device-hotplug.c @@ -110,3 +110,40 @@ int simple_drive_add(Monitor *mon, const QDict *qdict, QObject **ret_data) return 0; } + +int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + const char *id = qdict_get_str(qdict, "id"); + BlockDriverState *bs; + BlockDriverState **ptr; + Property *prop; + + bs = bdrv_find(id); + if (!bs) { + qerror_report(QERR_DEVICE_NOT_FOUND, id); + return -1; + } + + /* quiesce block driver; prevent further io */ + qemu_aio_flush(); + bdrv_flush(bs); + bdrv_close(bs); + + /* clean up guest state from pointing to host resource by + * finding and removing DeviceState "drive" property */ + for (prop = bs->peer->info->props; prop && prop->name; prop++) { + if (prop->info->type == PROP_TYPE_DRIVE) { + ptr = qdev_get_prop_ptr(bs->peer, prop); + if ((*ptr) == bs) { + bdrv_detach(bs, bs->peer); + *ptr = NULL; + break; + } + } + } + + /* clean up host side */ + drive_uninit(drive_get_by_blockdev(bs)); + + return 0; +} diff --git a/qemu-monitor.hx b/qemu-monitor.hx index e2c0c22..e66540c 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -162,6 +162,45 @@ Note: The "force" argument defaults to false. EQMP { + .name = RFQDN_REDHAT "drive_del", + .args_type = "id:s", + .params = "device", + .help = "remove host block device", + .user_print = monitor_user_noop, + .mhandler.cmd_new = do_drive_del, + }, + +STEXI +@item __com.redhat_drive_del @var{device} +@findex __com.redhat_drive_del +Remove host block device. The result is that guest generated IO is no longer +submitted against the host device underlying the disk. Once a drive has +been deleted, the QEMU Block layer returns -EIO which results in IO +errors in the guest for applications that are reading/writing to the device. +ETEXI +SQMP +__com.redhat_drive_del +---------- + + { +Remove host block device. The result is that guest generated IO is no longer +submitted against the host device underlying the disk. Once a drive has +been deleted, the QEMU Block layer returns -EIO which results in IO +errors in the guest for applications that are reading/writing to the device. + +Arguments: + +- "id": the device's ID (json-string) + +Example: + +-> { "execute": "drive_del", "arguments": { "id": "block1" } } +<- { "return": {} } + +EQMP + + { + .name = "change", .args_type = "device:B,target:F,arg:s?", .params = "device filename [format]", diff --git a/sysemu.h b/sysemu.h index ea5c3cc..13520db 100644 --- a/sysemu.h +++ b/sysemu.h @@ -225,6 +225,7 @@ void qemu_system_cpu_hot_add(int cpu, int state); DriveInfo *add_init_drive(const char *opts); int simple_drive_add(Monitor *mon, const QDict *qdict, QObject **ret_data); +int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data); /* pci-hotplug */ void pci_device_hot_add(Monitor *mon, const QDict *qdict); -- 1.7.3.2