diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2020-11-09 19:33:07 +0000 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2020-11-09 19:33:07 +0000 |
| commit | 2b030ce1ed75e075d35b0d1008a0cacd73624b28 (patch) | |
| tree | f339590f14578a646381692854e66a7f387c37dd /block.c | |
| parent | a2547c1ba911a0c53a10fe02d94a0f539dc064cc (diff) | |
| parent | d669ed6ab028497d634e1f236c74a98725f9e45f (diff) | |
| download | focaccia-qemu-2b030ce1ed75e075d35b0d1008a0cacd73624b28.tar.gz focaccia-qemu-2b030ce1ed75e075d35b0d1008a0cacd73624b28.zip | |
Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2020-11-09-v2' into staging
Block patches for 5.2.0-rc1: - Some nvme fixes (addressing problems spotted by Coverity) - Fix nfs compiling on mingw (and enable it in Cirrus) - Fix an error path in bdrv_co_invalidate_cache() (permission update was initiated, but not aborted) - Fix (on-error) roll back in bdrv_drop_intermediate(): Instead of inlining bdrv_replace_node() (wrongly), call that function - Fix for iotest 240 - Fix error handling in bdrv_getlength() - Be more explicit about how QCowL2Meta objects are handled - Cleanups # gpg: Signature made Mon 09 Nov 2020 17:45:06 GMT # gpg: using RSA key 91BEB60A30DB3E8857D11829F407DB0061D5CF40 # gpg: issuer "mreitz@redhat.com" # gpg: Good signature from "Max Reitz <mreitz@redhat.com>" [full] # Primary key fingerprint: 91BE B60A 30DB 3E88 57D1 1829 F407 DB00 61D5 CF40 * remotes/maxreitz/tags/pull-block-2020-11-09-v2: block: make bdrv_drop_intermediate() less wrong block: add bdrv_replace_node_common() block: add forgotten bdrv_abort_perm_update() to bdrv_co_invalidate_cache() block: Fix some code style problems, "foo* bar" should be "foo *bar" block: Fix integer promotion error in bdrv_getlength() block: enable libnfs on msys2/mingw in cirrus.yml block: Fixes nfs compiling error on msys2/mingw iotests: rewrite iotest 240 in python iotests: add filter_qmp_virtio_scsi function hw/block/nvme: fix free of array-typed value hw/block/nvme: fix uint16_t use of uint32_t sgls member hw/block/nvme: fix null ns in register namespace qcow2: Document and enforce the QCowL2Meta invariants block: Move bdrv_drain_all_end_quiesce() to block_int.h block: Remove unused include Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'block.c')
| -rw-r--r-- | block.c | 89 |
1 files changed, 54 insertions, 35 deletions
diff --git a/block.c b/block.c index 56bacc9e9f..f1cedac362 100644 --- a/block.c +++ b/block.c @@ -4563,8 +4563,16 @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to) return ret; } -void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, - Error **errp) +/* + * With auto_skip=true bdrv_replace_node_common skips updating from parents + * if it creates a parent-child relation loop or if parent is block-job. + * + * With auto_skip=false the error is returned if from has a parent which should + * not be updated. + */ +static void bdrv_replace_node_common(BlockDriverState *from, + BlockDriverState *to, + bool auto_skip, Error **errp) { BdrvChild *c, *next; GSList *list = NULL, *p; @@ -4583,7 +4591,12 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) { assert(c->bs == from); if (!should_update_child(c, to)) { - continue; + if (auto_skip) { + continue; + } + error_setg(errp, "Should not change '%s' link to '%s'", + c->name, from->node_name); + goto out; } if (c->frozen) { error_setg(errp, "Cannot change '%s' link to '%s'", @@ -4623,6 +4636,12 @@ out: bdrv_unref(from); } +void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, + Error **errp) +{ + return bdrv_replace_node_common(from, to, true, errp); +} + /* * Add new bs contents at the top of an image chain while the chain is * live, while keeping required fields on the top layer. @@ -4891,9 +4910,11 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, { BlockDriverState *explicit_top = top; bool update_inherits_from; - BdrvChild *c, *next; + BdrvChild *c; Error *local_err = NULL; int ret = -EIO; + g_autoptr(GSList) updated_children = NULL; + GSList *p; bdrv_ref(top); bdrv_subtree_drained_begin(top); @@ -4907,14 +4928,6 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, goto exit; } - /* This function changes all links that point to top and makes - * them point to base. Check that none of them is frozen. */ - QLIST_FOREACH(c, &top->parents, next_parent) { - if (c->frozen) { - goto exit; - } - } - /* If 'base' recursively inherits from 'top' then we should set * base->inherits_from to top->inherits_from after 'top' and all * other intermediate nodes have been dropped. @@ -4931,36 +4944,36 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, backing_file_str = base->filename; } - QLIST_FOREACH_SAFE(c, &top->parents, next_parent, next) { - /* Check whether we are allowed to switch c from top to base */ - GSList *ignore_children = g_slist_prepend(NULL, c); - ret = bdrv_check_update_perm(base, NULL, c->perm, c->shared_perm, - ignore_children, NULL, &local_err); - g_slist_free(ignore_children); - if (ret < 0) { - error_report_err(local_err); - goto exit; - } + QLIST_FOREACH(c, &top->parents, next_parent) { + updated_children = g_slist_prepend(updated_children, c); + } + + bdrv_replace_node_common(top, base, false, &local_err); + if (local_err) { + error_report_err(local_err); + goto exit; + } + + for (p = updated_children; p; p = p->next) { + c = p->data; - /* If so, update the backing file path in the image file */ if (c->klass->update_filename) { ret = c->klass->update_filename(c, base, backing_file_str, &local_err); if (ret < 0) { - bdrv_abort_perm_update(base); + /* + * TODO: Actually, we want to rollback all previous iterations + * of this loop, and (which is almost impossible) previous + * bdrv_replace_node()... + * + * Note, that c->klass->update_filename may lead to permission + * update, so it's a bad idea to call it inside permission + * update transaction of bdrv_replace_node. + */ error_report_err(local_err); goto exit; } } - - /* - * Do the actual switch in the in-memory graph. - * Completes bdrv_check_update_perm() transaction internally. - * c->frozen is false, we have checked that above. - */ - bdrv_ref(base); - bdrv_replace_child(c, base); - bdrv_unref(top); } if (update_inherits_from) { @@ -5091,8 +5104,13 @@ int64_t bdrv_getlength(BlockDriverState *bs) { int64_t ret = bdrv_nb_sectors(bs); - ret = ret > INT64_MAX / BDRV_SECTOR_SIZE ? -EFBIG : ret; - return ret < 0 ? ret : ret * BDRV_SECTOR_SIZE; + if (ret < 0) { + return ret; + } + if (ret > INT64_MAX / BDRV_SECTOR_SIZE) { + return -EFBIG; + } + return ret * BDRV_SECTOR_SIZE; } /* return 0 as number of sectors if no device present or error */ @@ -5782,6 +5800,7 @@ int coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp) bdrv_get_cumulative_perm(bs, &perm, &shared_perm); ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, NULL, errp); if (ret < 0) { + bdrv_abort_perm_update(bs); bs->open_flags |= BDRV_O_INACTIVE; return ret; } |