From f9092b108f7b35e463e58bd3dd348ff002ba9e63 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 25 Jun 2010 10:33:39 +0200 Subject: savevm: Survive hot-unplug of snapshot device savevm.c keeps a pointer to the snapshot block device. If you manage to get that device deleted, the pointer dangles, and the next snapshot operation will crash & burn. Unplugging a guest device that uses it does the trick: $ MALLOC_PERTURB_=234 qemu-system-x86_64 [...] QEMU 0.12.50 monitor - type 'help' for more information (qemu) info snapshots No available block device supports snapshots (qemu) drive_add auto if=none,file=tmp.qcow2 OK (qemu) device_add usb-storage,id=foo,drive=none1 (qemu) info snapshots Snapshot devices: none1 Snapshot list (from none1): ID TAG VM SIZE DATE VM CLOCK (qemu) device_del foo (qemu) info snapshots Snapshot devices: Segmentation fault (core dumped) Move management of that pointer to block.c, and zap it when the device it points becomes unusable. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- block.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'block.c') diff --git a/block.c b/block.c index 4c65035313..feda755294 100644 --- a/block.c +++ b/block.c @@ -63,6 +63,9 @@ static QTAILQ_HEAD(, BlockDriverState) bdrv_states = static QLIST_HEAD(, BlockDriver) bdrv_drivers = QLIST_HEAD_INITIALIZER(bdrv_drivers); +/* The device to use for VM snapshots */ +static BlockDriverState *bs_snapshots; + /* If non-zero, use only whitelisted block drivers */ static int use_bdrv_whitelist; @@ -629,6 +632,9 @@ unlink_and_fail: void bdrv_close(BlockDriverState *bs) { if (bs->drv) { + if (bs == bs_snapshots) { + bs_snapshots = NULL; + } if (bs->backing_hd) { bdrv_delete(bs->backing_hd); bs->backing_hd = NULL; @@ -677,6 +683,7 @@ void bdrv_delete(BlockDriverState *bs) bdrv_delete(bs->file); } + assert(bs != bs_snapshots); qemu_free(bs); } @@ -1778,6 +1785,25 @@ int bdrv_can_snapshot(BlockDriverState *bs) return 1; } +BlockDriverState *bdrv_snapshots(void) +{ + BlockDriverState *bs; + + if (bs_snapshots) + return bs_snapshots; + + bs = NULL; + while ((bs = bdrv_next(bs))) { + if (bdrv_can_snapshot(bs)) { + goto ok; + } + } + return NULL; + ok: + bs_snapshots = bs; + return bs; +} + int bdrv_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) { -- cgit v1.2.1