mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-28 20:41:52 -06:00
block/snapshot: move drain outside of read-locked bdrv_snapshot_delete()
This is in preparation to mark bdrv_drained_begin() as GRAPH_UNLOCKED. More granular draining is not trivially possible, because bdrv_snapshot_delete() can recursively call itself. The return value of bdrv_all_delete_snapshot() changes from -1 to -errno propagated from failed sub-calls. This is fine for the existing callers of bdrv_all_delete_snapshot(). Signed-off-by: Fiona Ebner <f.ebner@proxmox.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-ID: <20250530151125.955508-4-f.ebner@proxmox.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
e1d681b3e1
commit
d4c5f8c980
3 changed files with 34 additions and 19 deletions
|
@ -327,7 +327,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete an internal snapshot by @snapshot_id and @name.
|
* Delete an internal snapshot by @snapshot_id and @name.
|
||||||
* @bs: block device used in the operation
|
* @bs: block device used in the operation, must be drained
|
||||||
* @snapshot_id: unique snapshot ID, or NULL
|
* @snapshot_id: unique snapshot ID, or NULL
|
||||||
* @name: snapshot name, or NULL
|
* @name: snapshot name, or NULL
|
||||||
* @errp: location to store error
|
* @errp: location to store error
|
||||||
|
@ -358,6 +358,8 @@ int bdrv_snapshot_delete(BlockDriverState *bs,
|
||||||
|
|
||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
|
|
||||||
|
assert(bs->quiesce_counter > 0);
|
||||||
|
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
error_setg(errp, "Device '%s' has no medium",
|
error_setg(errp, "Device '%s' has no medium",
|
||||||
bdrv_get_device_name(bs));
|
bdrv_get_device_name(bs));
|
||||||
|
@ -368,9 +370,6 @@ int bdrv_snapshot_delete(BlockDriverState *bs,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* drain all pending i/o before deleting snapshot */
|
|
||||||
bdrv_drained_begin(bs);
|
|
||||||
|
|
||||||
if (drv->bdrv_snapshot_delete) {
|
if (drv->bdrv_snapshot_delete) {
|
||||||
ret = drv->bdrv_snapshot_delete(bs, snapshot_id, name, errp);
|
ret = drv->bdrv_snapshot_delete(bs, snapshot_id, name, errp);
|
||||||
} else if (fallback_bs) {
|
} else if (fallback_bs) {
|
||||||
|
@ -382,7 +381,6 @@ int bdrv_snapshot_delete(BlockDriverState *bs,
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_drained_end(bs);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,19 +569,22 @@ int bdrv_all_delete_snapshot(const char *name,
|
||||||
ERRP_GUARD();
|
ERRP_GUARD();
|
||||||
g_autoptr(GList) bdrvs = NULL;
|
g_autoptr(GList) bdrvs = NULL;
|
||||||
GList *iterbdrvs;
|
GList *iterbdrvs;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
|
||||||
|
|
||||||
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
|
bdrv_drain_all_begin();
|
||||||
return -1;
|
bdrv_graph_rdlock_main_loop();
|
||||||
|
|
||||||
|
ret = bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterbdrvs = bdrvs;
|
iterbdrvs = bdrvs;
|
||||||
while (iterbdrvs) {
|
while (iterbdrvs) {
|
||||||
BlockDriverState *bs = iterbdrvs->data;
|
BlockDriverState *bs = iterbdrvs->data;
|
||||||
QEMUSnapshotInfo sn1, *snapshot = &sn1;
|
QEMUSnapshotInfo sn1, *snapshot = &sn1;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if ((devices || bdrv_all_snapshots_includes_bs(bs)) &&
|
if ((devices || bdrv_all_snapshots_includes_bs(bs)) &&
|
||||||
bdrv_snapshot_find(bs, snapshot, name) >= 0)
|
bdrv_snapshot_find(bs, snapshot, name) >= 0)
|
||||||
|
@ -594,13 +595,16 @@ int bdrv_all_delete_snapshot(const char *name,
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_prepend(errp, "Could not delete snapshot '%s' on '%s': ",
|
error_prepend(errp, "Could not delete snapshot '%s' on '%s': ",
|
||||||
name, bdrv_get_device_or_node_name(bs));
|
name, bdrv_get_device_or_node_name(bs));
|
||||||
return -1;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterbdrvs = iterbdrvs->next;
|
iterbdrvs = iterbdrvs->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
out:
|
||||||
|
bdrv_graph_rdunlock_main_loop();
|
||||||
|
bdrv_drain_all_end();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
25
blockdev.c
25
blockdev.c
|
@ -1132,39 +1132,41 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
|
||||||
|
bdrv_drain_all_begin();
|
||||||
|
bdrv_graph_rdlock_main_loop();
|
||||||
|
|
||||||
bs = qmp_get_root_bs(device, errp);
|
bs = qmp_get_root_bs(device, errp);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!id && !name) {
|
if (!id && !name) {
|
||||||
error_setg(errp, "Name or id must be provided");
|
error_setg(errp, "Name or id must be provided");
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE, errp)) {
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE, errp)) {
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_snapshot_find_by_id_and_name(bs, id, name, &sn, &local_err);
|
ret = bdrv_snapshot_find_by_id_and_name(bs, id, name, &sn, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"Snapshot with id '%s' and name '%s' does not exist on "
|
"Snapshot with id '%s' and name '%s' does not exist on "
|
||||||
"device '%s'",
|
"device '%s'",
|
||||||
STR_OR_NULL(id), STR_OR_NULL(name), device);
|
STR_OR_NULL(id), STR_OR_NULL(name), device);
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_snapshot_delete(bs, id, name, &local_err);
|
bdrv_snapshot_delete(bs, id, name, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
info = g_new0(SnapshotInfo, 1);
|
info = g_new0(SnapshotInfo, 1);
|
||||||
|
@ -1180,6 +1182,9 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
|
||||||
info->has_icount = true;
|
info->has_icount = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
bdrv_graph_rdunlock_main_loop();
|
||||||
|
bdrv_drain_all_end();
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1295,12 +1300,14 @@ static void internal_snapshot_abort(void *opaque)
|
||||||
Error *local_error = NULL;
|
Error *local_error = NULL;
|
||||||
|
|
||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
|
||||||
|
|
||||||
if (!state->created) {
|
if (!state->created) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bdrv_drain_all_begin();
|
||||||
|
bdrv_graph_rdlock_main_loop();
|
||||||
|
|
||||||
if (bdrv_snapshot_delete(bs, sn->id_str, sn->name, &local_error) < 0) {
|
if (bdrv_snapshot_delete(bs, sn->id_str, sn->name, &local_error) < 0) {
|
||||||
error_reportf_err(local_error,
|
error_reportf_err(local_error,
|
||||||
"Failed to delete snapshot with id '%s' and "
|
"Failed to delete snapshot with id '%s' and "
|
||||||
|
@ -1308,6 +1315,8 @@ static void internal_snapshot_abort(void *opaque)
|
||||||
sn->id_str, sn->name,
|
sn->id_str, sn->name,
|
||||||
bdrv_get_device_name(bs));
|
bdrv_get_device_name(bs));
|
||||||
}
|
}
|
||||||
|
bdrv_graph_rdunlock_main_loop();
|
||||||
|
bdrv_drain_all_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void internal_snapshot_clean(void *opaque)
|
static void internal_snapshot_clean(void *opaque)
|
||||||
|
|
|
@ -3505,6 +3505,7 @@ static int img_snapshot(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SNAPSHOT_DELETE:
|
case SNAPSHOT_DELETE:
|
||||||
|
bdrv_drain_all_begin();
|
||||||
bdrv_graph_rdlock_main_loop();
|
bdrv_graph_rdlock_main_loop();
|
||||||
ret = bdrv_snapshot_find(bs, &sn, snapshot_name);
|
ret = bdrv_snapshot_find(bs, &sn, snapshot_name);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -3520,6 +3521,7 @@ static int img_snapshot(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bdrv_graph_rdunlock_main_loop();
|
bdrv_graph_rdunlock_main_loop();
|
||||||
|
bdrv_drain_all_end();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue