From: Max Reitz <mreitz@redhat.com>
To: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>,
"qemu-block@nongnu.org" <qemu-block@nongnu.org>
Cc: Kevin Wolf <kwolf@redhat.com>,
"qemu-devel@nongnu.org" <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] [PATCH v5 09/42] block: Include filters when freezing backing chain
Date: Thu, 13 Jun 2019 16:05:43 +0200 [thread overview]
Message-ID: <e4832ffc-62bd-bbaa-a00b-71fedf4d52bc@redhat.com> (raw)
In-Reply-To: <d6074caa-ee1e-4dde-1977-83ab327e2771@virtuozzo.com>
[-- Attachment #1.1: Type: text/plain, Size: 7449 bytes --]
On 13.06.19 15:04, Vladimir Sementsov-Ogievskiy wrote:
> 13.06.2019 1:09, Max Reitz wrote:
>> In order to make filters work in backing chains, the associated
>> functions must be able to deal with them and freeze all filter links, be
>> they COW or R/W filter links.
>>
>> While at it, add some comments that note which functions require their
>> caller to ensure that a given child link is not frozen, and how the
>> callers do so.
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>> block.c | 45 ++++++++++++++++++++++++++++++++-------------
>> 1 file changed, 32 insertions(+), 13 deletions(-)
>>
>> diff --git a/block.c b/block.c
>> index 8438b0699e..45882a3470 100644
>> --- a/block.c
>> +++ b/block.c
>> @@ -2214,12 +2214,15 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
>> * If @new_bs is not NULL, bdrv_check_perm() must be called beforehand, as this
>> * function uses bdrv_set_perm() to update the permissions according to the new
>> * reference that @new_bs gets.
>> + *
>> + * Callers must ensure that child->frozen is false.
>> */
>> static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
>> {
>> BlockDriverState *old_bs = child->bs;
>> uint64_t perm, shared_perm;
>>
>> + /* Asserts that child->frozen == false */
>> bdrv_replace_child_noperm(child, new_bs);
>>
>> if (old_bs) {
>> @@ -2360,6 +2363,7 @@ static void bdrv_detach_child(BdrvChild *child)
>> g_free(child);
>> }
>>
>> +/* Callers must ensure that child->frozen is false. */
>
> Is such a comment better than one-line extra assertion at start of the function body?
Well, there already is an assertion, it is in
bdrv_replace_child_noperm(). I personally prefer to read comments than
assertions.
>> void bdrv_root_unref_child(BdrvChild *child)
>> {
>> BlockDriverState *child_bs;
>> @@ -2369,6 +2373,7 @@ void bdrv_root_unref_child(BdrvChild *child)
>> bdrv_unref(child_bs);
>> }
>>
>> +/* Callers must ensure that child->frozen is false. */
>> void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child)
>> {
>> if (child == NULL) {
>> @@ -2435,6 +2440,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
>> }
>>
>> if (bs->backing) {
>> + /* Cannot be frozen, we checked that above */
>> bdrv_unref_child(bs, bs->backing);
>> }
>>
>> @@ -3908,6 +3914,7 @@ static void bdrv_close(BlockDriverState *bs)
>>
>> if (bs->drv) {
>> if (bs->drv->bdrv_close) {
>> + /* Must unfreeze all children, so bdrv_unref_child() works */
>> bs->drv->bdrv_close(bs);
>> }
>> bs->drv = NULL;
>> @@ -4281,17 +4288,20 @@ BlockDriverState *bdrv_find_base(BlockDriverState *bs)
>> * Return true if at least one of the backing links between @bs and
>> * @base is frozen. @errp is set if that's the case.
>> * @base must be reachable from @bs, or NULL.
>> + * (Filters are treated as normal elements of the backing chain.)
>> */
>> bool bdrv_is_backing_chain_frozen(BlockDriverState *bs, BlockDriverState *base,
>> Error **errp)
>> {
>> BlockDriverState *i;
>> + BdrvChild *child;
>>
>> - for (i = bs; i != base; i = backing_bs(i)) {
>> - if (i->backing && i->backing->frozen) {
>> + for (i = bs; i != base; i = child_bs(child)) {
>> + child = bdrv_filtered_child(i);
>> +
>> + if (child && child->frozen) {
>> error_setg(errp, "Cannot change '%s' link from '%s' to '%s'",
>> - i->backing->name, i->node_name,
>> - backing_bs(i)->node_name);
>> + child->name, i->node_name, child->bs->node_name);
>> return true;
>> }
>> }
>> @@ -4305,19 +4315,22 @@ bool bdrv_is_backing_chain_frozen(BlockDriverState *bs, BlockDriverState *base,
>> * none of the links are modified.
>> * @base must be reachable from @bs, or NULL.
>> * Returns 0 on success. On failure returns < 0 and sets @errp.
>> + * (Filters are treated as normal elements of the backing chain.)
>> */
>> int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
>> Error **errp)
>> {
>> BlockDriverState *i;
>> + BdrvChild *child;
>>
>> if (bdrv_is_backing_chain_frozen(bs, base, errp)) {
>> return -EPERM;
>> }
>>
>> - for (i = bs; i != base; i = backing_bs(i)) {
>> - if (i->backing) {
>> - i->backing->frozen = true;
>> + for (i = bs; i != base; i = child_bs(child)) {
>> + child = bdrv_filtered_child(i);
>> + if (child) {
>> + child->frozen = true;
>> }
>> }
>>
>> @@ -4328,15 +4341,18 @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
>> * Unfreeze all backing links between @bs and @base. The caller must
>> * ensure that all links are frozen before using this function.
>> * @base must be reachable from @bs, or NULL.
>> + * (Filters are treated as normal elements of the backing chain.)
>> */
>> void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base)
>> {
>> BlockDriverState *i;
>> + BdrvChild *child;
>>
>> - for (i = bs; i != base; i = backing_bs(i)) {
>> - if (i->backing) {
>> - assert(i->backing->frozen);
>> - i->backing->frozen = false;
>> + for (i = bs; i != base; i = child_bs(child)) {
>> + child = bdrv_filtered_child(i);
>> + if (child) {
>> + assert(child->frozen);
>> + child->frozen = false;
>> }
>> }
>> }
>> @@ -4438,8 +4454,11 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
>> }
>> }
>>
>> - /* Do the actual switch in the in-memory graph.
>> - * Completes bdrv_check_update_perm() transaction internally. */
>> + /*
>> + * 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);
>>
>
> Hmm, OK, it's better than it was, so:
> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
>
> But I have one thought: we check that frozen is false at some point, and then
> do some logic around this child. Where is guarantee, that someone else will not
> set frozen=true during some yield, for example? So, do we need a kind of child_mutex,
> or something like this?
The guarantee is that the caller does not do anything that could cause
the child link to become frozen between checking whether it is and
performing an operation that relies on it not being frozen.
Freezing (currently) only happens when starting block jobs, which can
only happen because of monitor commands. Even in
bdrv_drop_intermediate(), which has quite a bit of code between checking
the frozen status and calling bdrv_replace_child(), I don’t see how a
new block job could sneak in.
Max
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
next prev parent reply other threads:[~2019-06-13 15:37 UTC|newest]
Thread overview: 113+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-12 22:09 [Qemu-devel] [PATCH v5 00/42] block: Deal with filters Max Reitz
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 01/42] block: Mark commit and mirror as filter drivers Max Reitz
2019-06-13 10:47 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 02/42] copy-on-read: Support compressed writes Max Reitz
2019-06-13 10:49 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 03/42] throttle: " Max Reitz
2019-06-13 10:51 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 04/42] block: Add child access functions Max Reitz
2019-06-13 12:15 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 05/42] block: Add chain helper functions Max Reitz
2019-06-13 12:26 ` Vladimir Sementsov-Ogievskiy
2019-06-13 12:33 ` Max Reitz
2019-06-13 12:39 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 06/42] qcow2: Implement .bdrv_storage_child() Max Reitz
2019-06-13 12:27 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 07/42] block: *filtered_cow_child() for *has_zero_init() Max Reitz
2019-06-13 12:34 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 08/42] block: bdrv_set_backing_hd() is about bs->backing Max Reitz
2019-06-13 12:40 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 09/42] block: Include filters when freezing backing chain Max Reitz
2019-06-13 13:04 ` Vladimir Sementsov-Ogievskiy
2019-06-13 14:05 ` Max Reitz [this message]
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 10/42] block: Use CAF in bdrv_is_encrypted() Max Reitz
2019-06-13 13:16 ` Vladimir Sementsov-Ogievskiy
2019-06-13 14:15 ` Max Reitz
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 11/42] block: Add bdrv_supports_compressed_writes() Max Reitz
2019-06-13 13:29 ` Vladimir Sementsov-Ogievskiy
2019-06-13 14:19 ` Max Reitz
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 12/42] block: Use bdrv_filtered_rw* where obvious Max Reitz
2019-06-13 13:37 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 13/42] block: Use CAFs in block status functions Max Reitz
2019-06-14 12:07 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 14/42] block: Use CAFs when working with backing chains Max Reitz
2019-06-14 13:26 ` Vladimir Sementsov-Ogievskiy
2019-06-14 13:50 ` Max Reitz
2019-06-14 14:31 ` Vladimir Sementsov-Ogievskiy
2019-06-14 16:02 ` Max Reitz
2019-06-14 16:39 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 15/42] block: Re-evaluate backing file handling in reopen Max Reitz
2019-06-14 13:42 ` Vladimir Sementsov-Ogievskiy
2019-06-14 15:52 ` Max Reitz
2019-06-14 16:43 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 16/42] block: Use child access functions when flushing Max Reitz
2019-06-14 14:01 ` Vladimir Sementsov-Ogievskiy
2019-06-14 15:55 ` Max Reitz
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 17/42] block: Use CAFs in bdrv_refresh_limits() Max Reitz
2019-06-14 15:04 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 18/42] block: Use CAFs in bdrv_refresh_filename() Max Reitz
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 19/42] block: Use CAF in bdrv_co_rw_vmstate() Max Reitz
2019-06-14 15:14 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 20/42] block/snapshot: Fall back to storage child Max Reitz
2019-06-14 15:22 ` Vladimir Sementsov-Ogievskiy
2019-06-14 16:10 ` Max Reitz
2019-06-14 16:47 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 21/42] block: Use CAFs for debug breakpoints Max Reitz
2019-06-14 15:29 ` Vladimir Sementsov-Ogievskiy
2019-06-14 16:12 ` Max Reitz
2019-06-14 20:28 ` Eric Blake
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 22/42] block: Use CAFs in bdrv_get_allocated_file_size() Max Reitz
2019-06-12 22:17 ` Max Reitz
2019-06-14 15:41 ` Vladimir Sementsov-Ogievskiy
2019-06-14 16:15 ` Max Reitz
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 23/42] blockdev: Use CAF in external_snapshot_prepare() Max Reitz
2019-06-14 15:46 ` Vladimir Sementsov-Ogievskiy
2019-06-14 16:20 ` Max Reitz
2019-06-14 16:58 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 24/42] block: Use child access functions for QAPI queries Max Reitz
2019-06-18 12:06 ` Vladimir Sementsov-Ogievskiy
2019-06-18 14:22 ` Max Reitz
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 25/42] mirror: Deal with filters Max Reitz
2019-06-18 13:12 ` Vladimir Sementsov-Ogievskiy
2019-06-18 14:47 ` Max Reitz
2019-06-18 14:55 ` Vladimir Sementsov-Ogievskiy
2019-06-18 15:20 ` Max Reitz
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 26/42] backup: " Max Reitz
2019-06-18 13:45 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 27/42] commit: " Max Reitz
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 28/42] stream: " Max Reitz
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 29/42] nbd: Use CAF when looking for dirty bitmap Max Reitz
2019-06-18 13:58 ` Vladimir Sementsov-Ogievskiy
2019-06-18 14:48 ` Eric Blake
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 30/42] qemu-img: Use child access functions Max Reitz
2019-06-19 9:18 ` Vladimir Sementsov-Ogievskiy
2019-06-19 15:49 ` Max Reitz
2019-06-21 13:15 ` Vladimir Sementsov-Ogievskiy
2019-07-24 9:54 ` Vladimir Sementsov-Ogievskiy
2019-07-25 16:34 ` Max Reitz
2019-07-26 13:44 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 31/42] block: Drop backing_bs() Max Reitz
2019-06-19 9:18 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 32/42] block: Make bdrv_get_cumulative_perm() public Max Reitz
2019-06-19 9:19 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 33/42] blockdev: Fix active commit choice Max Reitz
2019-06-19 9:31 ` Vladimir Sementsov-Ogievskiy
2019-06-19 15:59 ` Max Reitz
2019-06-21 13:26 ` Vladimir Sementsov-Ogievskiy
2019-07-24 9:54 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 34/42] block: Inline bdrv_co_block_status_from_*() Max Reitz
2019-06-19 9:34 ` Vladimir Sementsov-Ogievskiy
2019-06-19 16:01 ` Max Reitz
2019-06-19 16:07 ` Max Reitz
2019-06-21 13:39 ` Vladimir Sementsov-Ogievskiy
2019-07-24 9:54 ` Vladimir Sementsov-Ogievskiy
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 35/42] block: Fix check_to_replace_node() Max Reitz
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 36/42] iotests: Add tests for mirror @replaces loops Max Reitz
2019-06-12 22:09 ` [Qemu-devel] [PATCH v5 37/42] block: Leave BDS.backing_file constant Max Reitz
2019-06-12 22:10 ` [Qemu-devel] [PATCH v5 38/42] iotests: Let complete_and_wait() work with commit Max Reitz
2019-06-12 22:10 ` [Qemu-devel] [PATCH v5 39/42] iotests: Add filter commit test cases Max Reitz
2019-06-12 22:10 ` [Qemu-devel] [PATCH v5 40/42] iotests: Add filter mirror " Max Reitz
2019-06-12 22:10 ` [Qemu-devel] [PATCH v5 41/42] iotests: Add test for commit in sub directory Max Reitz
2019-06-12 22:10 ` [Qemu-devel] [PATCH v5 42/42] iotests: Test committing to overridden backing Max Reitz
2019-06-13 15:28 ` [Qemu-devel] [PATCH v5 00/42] block: Deal with filters Vladimir Sementsov-Ogievskiy
2019-06-13 16:12 ` Max Reitz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e4832ffc-62bd-bbaa-a00b-71fedf4d52bc@redhat.com \
--to=mreitz@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=vsementsov@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).