block: Mark bdrv_snapshot_fallback() and callers GRAPH_RDLOCK

This adds GRAPH_RDLOCK annotations to declare that callers of
bdrv_snapshot_fallback() need to hold a reader lock for the graph
because it accesses the children list of a node.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-ID: <20230929145157.45443-8-kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
master
Kevin Wolf 2023-09-29 16:51:42 +02:00
parent 7859c45a46
commit a32e781838
5 changed files with 67 additions and 24 deletions

View File

@ -155,11 +155,15 @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
* back if the given BDS does not support snapshots.
* Return NULL if there is no BDS to (safely) fall back to.
*/
static BdrvChild *bdrv_snapshot_fallback_child(BlockDriverState *bs)
static BdrvChild * GRAPH_RDLOCK
bdrv_snapshot_fallback_child(BlockDriverState *bs)
{
BdrvChild *fallback = bdrv_primary_child(bs);
BdrvChild *child;
GLOBAL_STATE_CODE();
assert_bdrv_graph_readable();
/* We allow fallback only to primary child */
if (!fallback) {
return NULL;
@ -182,8 +186,10 @@ static BdrvChild *bdrv_snapshot_fallback_child(BlockDriverState *bs)
return fallback;
}
static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs)
static BlockDriverState * GRAPH_RDLOCK
bdrv_snapshot_fallback(BlockDriverState *bs)
{
GLOBAL_STATE_CODE();
return child_bs(bdrv_snapshot_fallback_child(bs));
}
@ -254,7 +260,10 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
return ret;
}
bdrv_graph_rdlock_main_loop();
fallback = bdrv_snapshot_fallback_child(bs);
bdrv_graph_rdunlock_main_loop();
if (fallback) {
QDict *options;
QDict *file_options;
@ -374,10 +383,12 @@ int bdrv_snapshot_delete(BlockDriverState *bs,
int bdrv_snapshot_list(BlockDriverState *bs,
QEMUSnapshotInfo **psn_info)
{
GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();
BlockDriver *drv = bs->drv;
BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs);
GLOBAL_STATE_CODE();
if (!drv) {
return -ENOMEDIUM;
}
@ -498,6 +509,9 @@ bdrv_all_get_snapshot_devices(bool has_devices, strList *devices,
static bool GRAPH_RDLOCK bdrv_all_snapshots_includes_bs(BlockDriverState *bs)
{
GLOBAL_STATE_CODE();
assert_bdrv_graph_readable();
if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
return false;
}
@ -595,11 +609,15 @@ int bdrv_all_goto_snapshot(const char *name,
{
g_autoptr(GList) bdrvs = NULL;
GList *iterbdrvs;
int ret;
GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
bdrv_graph_rdlock_main_loop();
ret = bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp);
bdrv_graph_rdunlock_main_loop();
if (ret < 0) {
return -1;
}
@ -608,9 +626,14 @@ int bdrv_all_goto_snapshot(const char *name,
BlockDriverState *bs = iterbdrvs->data;
AioContext *ctx = bdrv_get_aio_context(bs);
int ret = 0;
bool all_snapshots_includes_bs;
aio_context_acquire(ctx);
if (devices || bdrv_all_snapshots_includes_bs(bs)) {
bdrv_graph_rdlock_main_loop();
all_snapshots_includes_bs = bdrv_all_snapshots_includes_bs(bs);
bdrv_graph_rdunlock_main_loop();
if (devices || all_snapshots_includes_bs) {
ret = bdrv_snapshot_goto(bs, name, errp);
}
aio_context_release(ctx);

View File

@ -1138,6 +1138,9 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
SnapshotInfo *info = NULL;
int ret;
GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();
bs = qmp_get_root_bs(device, errp);
if (!bs) {
return NULL;
@ -1223,6 +1226,9 @@ static void internal_snapshot_action(BlockdevSnapshotInternal *internal,
AioContext *aio_context;
int ret1;
GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();
tran_add(tran, &internal_snapshot_drv, state);
device = internal->device;
@ -1311,6 +1317,9 @@ static void internal_snapshot_abort(void *opaque)
AioContext *aio_context;
Error *local_error = NULL;
GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();
if (!state->created) {
return;
}

View File

@ -313,14 +313,16 @@ struct BlockDriver {
int GRAPH_RDLOCK_PTR (*bdrv_inactivate)(BlockDriverState *bs);
int (*bdrv_snapshot_create)(BlockDriverState *bs,
QEMUSnapshotInfo *sn_info);
int (*bdrv_snapshot_goto)(BlockDriverState *bs,
const char *snapshot_id);
int (*bdrv_snapshot_delete)(BlockDriverState *bs,
const char *snapshot_id,
const char *name,
Error **errp);
int GRAPH_RDLOCK_PTR (*bdrv_snapshot_create)(
BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
int GRAPH_UNLOCKED_PTR (*bdrv_snapshot_goto)(
BlockDriverState *bs, const char *snapshot_id);
int GRAPH_RDLOCK_PTR (*bdrv_snapshot_delete)(
BlockDriverState *bs, const char *snapshot_id, const char *name,
Error **errp);
int (*bdrv_snapshot_list)(BlockDriverState *bs,
QEMUSnapshotInfo **psn_info);
int (*bdrv_snapshot_load_tmp)(BlockDriverState *bs,

View File

@ -25,6 +25,7 @@
#ifndef SNAPSHOT_H
#define SNAPSHOT_H
#include "block/graph-lock.h"
#include "qapi/qapi-builtin-types.h"
#define SNAPSHOT_OPT_BASE "snapshot."
@ -59,16 +60,19 @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
const char *name,
QEMUSnapshotInfo *sn_info,
Error **errp);
int bdrv_can_snapshot(BlockDriverState *bs);
int bdrv_snapshot_create(BlockDriverState *bs,
QEMUSnapshotInfo *sn_info);
int bdrv_snapshot_goto(BlockDriverState *bs,
const char *snapshot_id,
Error **errp);
int bdrv_snapshot_delete(BlockDriverState *bs,
const char *snapshot_id,
const char *name,
Error **errp);
int GRAPH_RDLOCK bdrv_can_snapshot(BlockDriverState *bs);
int GRAPH_RDLOCK
bdrv_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
int GRAPH_UNLOCKED
bdrv_snapshot_goto(BlockDriverState *bs, const char *snapshot_id, Error **errp);
int GRAPH_RDLOCK
bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id,
const char *name, Error **errp);
int bdrv_snapshot_list(BlockDriverState *bs,
QEMUSnapshotInfo **psn_info);
int bdrv_snapshot_load_tmp(BlockDriverState *bs,

View File

@ -3470,7 +3470,10 @@ static int img_snapshot(int argc, char **argv)
sn.date_sec = rt / G_USEC_PER_SEC;
sn.date_nsec = (rt % G_USEC_PER_SEC) * 1000;
bdrv_graph_rdlock_main_loop();
ret = bdrv_snapshot_create(bs, &sn);
bdrv_graph_rdunlock_main_loop();
if (ret) {
error_report("Could not create snapshot '%s': %s",
snapshot_name, strerror(-ret));
@ -3486,6 +3489,7 @@ static int img_snapshot(int argc, char **argv)
break;
case SNAPSHOT_DELETE:
bdrv_graph_rdlock_main_loop();
ret = bdrv_snapshot_find(bs, &sn, snapshot_name);
if (ret < 0) {
error_report("Could not delete snapshot '%s': snapshot not "
@ -3499,6 +3503,7 @@ static int img_snapshot(int argc, char **argv)
ret = 1;
}
}
bdrv_graph_rdunlock_main_loop();
break;
}