diff options
| author | Stefan Hajnoczi <stefanha@redhat.com> | 2025-02-10 13:25:36 -0500 |
|---|---|---|
| committer | Stefan Hajnoczi <stefanha@redhat.com> | 2025-02-10 13:25:36 -0500 |
| commit | f2ec48fefd172a8dd20cb0073087d659aca9578c (patch) | |
| tree | 72bfa22dcc37323db150fb94c00864cc49874088 /block.c | |
| parent | 4f1d01851270ac7457a83a7615a40bf518d54602 (diff) | |
| parent | fc4e394b2887e15d5f83994e4fc7b26c895c627a (diff) | |
| download | focaccia-qemu-f2ec48fefd172a8dd20cb0073087d659aca9578c.tar.gz focaccia-qemu-f2ec48fefd172a8dd20cb0073087d659aca9578c.zip | |
Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging
Block layer patches - Managing inactive nodes (enables QSD migration with shared storage) - Fix swapped values for BLOCK_IO_ERROR 'device' and 'qom-path' - vpc: Read images exported from Azure correctly - scripts/qemu-gdb: Support coroutine dumps in coredumps - Minor cleanups # -----BEGIN PGP SIGNATURE----- # # iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmek34IRHGt3b2xmQHJl # ZGhhdC5jb20ACgkQfwmycsiPL9bDpxAAnTvwmdazAXG0g9GzqvrEB/+6rStjAsqE # 9MTWV4WxyN41d0RXxN8CYKb8CXSiTRyw6r3CSGNYEI2eShe9e934PriSkZm41HyX # n9Yh5YxqGZqitzvPtx62Ii/1KG+PcjQbfHuK1p4+rlKa0yQ2eGlio1JIIrZrCkBZ # ikZcQUrhIyD0XV8hTQ2+Ysa+ZN6itjnlTQIG3gS3m8f8WR7kyUXD8YFMQFJFyjVx # NrAIpLnc/ln9+5PZR9tje8U7XEn2KCgI5pgGaQnrd0h0G1H4ig8ogzYYnKTLhjU/ # AmQpS8np8Tyg6S1UZTiekEq0VuAhThEQc5b3sGbmHWH/R2ABMStyf18oCBAkPzZ7 # s6h+3XzTKKY2Q5Q3ZG/ANkUJjTNBhdj1fcaARvbSWsqsuk5CWX/I3jzvgihFtCSs # eGu+b/bLeW6P7hu4qPHBcgLHuB1Fc7Rd2t4BoIGM1wcO2CeC9DzUKOiIMZOEJIh0 # GGqCkEWDHgckDTakD4/vSqm0UDKt6FSlQC9ga/ILBY3IB5HpHoArY58selymy28i # X7MgAvbjdsmNuUuXDZZOiObcFt3j8jlmwPJpPyzXPQIiPX1RXeBPRhVAEeZCKn6Z # tfHr72SJdMeVOGXVTvOrJ2iW+4g03rPdmkDFCUhpOwo62RODq7ahvCIXsNf3nEFR # rSB3T1M/8EM= # =iQLP # -----END PGP SIGNATURE----- # gpg: Signature made Thu 06 Feb 2025 11:12:50 EST # gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6 # gpg: issuer "kwolf@redhat.com" # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full] # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * tag 'for-upstream' of https://repo.or.cz/qemu/kevin: (25 commits) block: remove unused BLOCK_OP_TYPE_DATAPLANE iotests: Add (NBD-based) tests for inactive nodes iotests: Add qsd-migrate case iotests: Add filter_qtest() nbd/server: Support inactive nodes block/export: Add option to allow export of inactive nodes block: Drain nodes before inactivating them block/export: Don't ignore image activation error in blk_exp_add() block: Support inactive nodes in blk_insert_bs() block: Add blockdev-set-active QMP command block: Add option to create inactive nodes block: Fix crash on block_resize on inactive node block: Don't attach inactive child to active node migration/block-active: Remove global active flag block: Inactivate external snapshot overlays when necessary block: Allow inactivating already inactive nodes block: Add 'active' field to BlockDeviceInfo block-backend: Fix argument order when calling 'qapi_event_send_block_io_error()' scripts/qemu-gdb: Support coroutine dumps in coredumps scripts/qemu-gdb: Simplify fs_base fetching for coroutines ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block.c')
| -rw-r--r-- | block.c | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/block.c b/block.c index b4459dee2e..0ece805e41 100644 --- a/block.c +++ b/block.c @@ -1573,6 +1573,10 @@ static void update_flags_from_options(int *flags, QemuOpts *opts) if (qemu_opt_get_bool_del(opts, BDRV_OPT_AUTO_READ_ONLY, false)) { *flags |= BDRV_O_AUTO_RDONLY; } + + if (!qemu_opt_get_bool_del(opts, BDRV_OPT_ACTIVE, true)) { + *flags |= BDRV_O_INACTIVE; + } } static void update_options_from_flags(QDict *options, int flags) @@ -1800,6 +1804,11 @@ QemuOptsList bdrv_runtime_opts = { .help = "Ignore flush requests", }, { + .name = BDRV_OPT_ACTIVE, + .type = QEMU_OPT_BOOL, + .help = "Node is activated", + }, + { .name = BDRV_OPT_READ_ONLY, .type = QEMU_OPT_BOOL, .help = "Node is opened in read-only mode", @@ -3077,6 +3086,13 @@ bdrv_attach_child_common(BlockDriverState *child_bs, assert(child_class->get_parent_desc); GLOBAL_STATE_CODE(); + if (bdrv_is_inactive(child_bs) && (perm & ~BLK_PERM_CONSISTENT_READ)) { + g_autofree char *perm_names = bdrv_perm_names(perm); + error_setg(errp, "Permission '%s' unavailable on inactive node", + perm_names); + return NULL; + } + new_child = g_new(BdrvChild, 1); *new_child = (BdrvChild) { .bs = NULL, @@ -3183,6 +3199,11 @@ bdrv_attach_child_noperm(BlockDriverState *parent_bs, child_bs->node_name, child_name, parent_bs->node_name); return NULL; } + if (bdrv_is_inactive(child_bs) && !bdrv_is_inactive(parent_bs)) { + error_setg(errp, "Inactive '%s' can't be a %s child of active '%s'", + child_bs->node_name, child_name, parent_bs->node_name); + return NULL; + } bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm); bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL, @@ -6824,6 +6845,10 @@ void bdrv_init_with_whitelist(void) bdrv_init(); } +bool bdrv_is_inactive(BlockDriverState *bs) { + return bs->open_flags & BDRV_O_INACTIVE; +} + int bdrv_activate(BlockDriverState *bs, Error **errp) { BdrvChild *child, *parent; @@ -6955,7 +6980,8 @@ bdrv_has_bds_parent(BlockDriverState *bs, bool only_active) return false; } -static int GRAPH_RDLOCK bdrv_inactivate_recurse(BlockDriverState *bs) +static int GRAPH_RDLOCK +bdrv_inactivate_recurse(BlockDriverState *bs, bool top_level) { BdrvChild *child, *parent; int ret; @@ -6973,7 +6999,14 @@ static int GRAPH_RDLOCK bdrv_inactivate_recurse(BlockDriverState *bs) return 0; } - assert(!(bs->open_flags & BDRV_O_INACTIVE)); + /* + * Inactivating an already inactive node on user request is harmless, but if + * a child is already inactive before its parent, that's bad. + */ + if (bs->open_flags & BDRV_O_INACTIVE) { + assert(top_level); + return 0; + } /* Inactivate this node */ if (bs->drv->bdrv_inactivate) { @@ -6999,7 +7032,9 @@ static int GRAPH_RDLOCK bdrv_inactivate_recurse(BlockDriverState *bs) return -EPERM; } + bdrv_drained_begin(bs); bs->open_flags |= BDRV_O_INACTIVE; + bdrv_drained_end(bs); /* * Update permissions, they may differ for inactive nodes. @@ -7010,7 +7045,7 @@ static int GRAPH_RDLOCK bdrv_inactivate_recurse(BlockDriverState *bs) /* Recursively inactivate children */ QLIST_FOREACH(child, &bs->children, next) { - ret = bdrv_inactivate_recurse(child->bs); + ret = bdrv_inactivate_recurse(child->bs, false); if (ret < 0) { return ret; } @@ -7019,6 +7054,27 @@ static int GRAPH_RDLOCK bdrv_inactivate_recurse(BlockDriverState *bs) return 0; } +int bdrv_inactivate(BlockDriverState *bs, Error **errp) +{ + int ret; + + GLOBAL_STATE_CODE(); + GRAPH_RDLOCK_GUARD_MAINLOOP(); + + if (bdrv_has_bds_parent(bs, true)) { + error_setg(errp, "Node has active parent node"); + return -EPERM; + } + + ret = bdrv_inactivate_recurse(bs, true); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to inactivate node"); + return ret; + } + + return 0; +} + int bdrv_inactivate_all(void) { BlockDriverState *bs = NULL; @@ -7035,7 +7091,7 @@ int bdrv_inactivate_all(void) if (bdrv_has_bds_parent(bs, false)) { continue; } - ret = bdrv_inactivate_recurse(bs); + ret = bdrv_inactivate_recurse(bs, true); if (ret < 0) { bdrv_next_cleanup(&it); break; |