block: check bdrv_in_use() before blockdev operations
Long-running block operations like block migration and image streaming must have continual access to their block device. It is not safe to perform operations like hotplug, eject, change, resize, commit, or external snapshot while a long-running operation is in progress. This patch adds the missing bdrv_in_use() checks so that block migration and image streaming never have the rug pulled out from underneath them. Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
7e6246670a
commit
2d3735d3bf
4
block.c
4
block.c
@ -1020,6 +1020,10 @@ int bdrv_commit(BlockDriverState *bs)
|
|||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bdrv_in_use(bs) || bdrv_in_use(bs->backing_hd)) {
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
backing_drv = bs->backing_hd->drv;
|
backing_drv = bs->backing_hd->drv;
|
||||||
ro = bs->backing_hd->read_only;
|
ro = bs->backing_hd->read_only;
|
||||||
strncpy(filename, bs->backing_hd->filename, sizeof(filename));
|
strncpy(filename, bs->backing_hd->filename, sizeof(filename));
|
||||||
|
16
blockdev.c
16
blockdev.c
@ -592,12 +592,18 @@ void do_commit(Monitor *mon, const QDict *qdict)
|
|||||||
if (!strcmp(device, "all")) {
|
if (!strcmp(device, "all")) {
|
||||||
bdrv_commit_all();
|
bdrv_commit_all();
|
||||||
} else {
|
} else {
|
||||||
|
int ret;
|
||||||
|
|
||||||
bs = bdrv_find(device);
|
bs = bdrv_find(device);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
qerror_report(QERR_DEVICE_NOT_FOUND, device);
|
qerror_report(QERR_DEVICE_NOT_FOUND, device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bdrv_commit(bs);
|
ret = bdrv_commit(bs);
|
||||||
|
if (ret == -EBUSY) {
|
||||||
|
qerror_report(QERR_DEVICE_IN_USE, device);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -616,6 +622,10 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
|
|||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (bdrv_in_use(bs)) {
|
||||||
|
error_set(errp, QERR_DEVICE_IN_USE, device);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pstrcpy(old_filename, sizeof(old_filename), bs->filename);
|
pstrcpy(old_filename, sizeof(old_filename), bs->filename);
|
||||||
|
|
||||||
@ -667,6 +677,10 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
|
|||||||
|
|
||||||
static void eject_device(BlockDriverState *bs, int force, Error **errp)
|
static void eject_device(BlockDriverState *bs, int force, Error **errp)
|
||||||
{
|
{
|
||||||
|
if (bdrv_in_use(bs)) {
|
||||||
|
error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!bdrv_dev_has_removable_media(bs)) {
|
if (!bdrv_dev_has_removable_media(bs)) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_REMOVABLE, bdrv_get_device_name(bs));
|
error_set(errp, QERR_DEVICE_NOT_REMOVABLE, bdrv_get_device_name(bs));
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user