[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH for-5.0 v2 06/23] block: Add bdrv_recurse_can_replace()
From: |
Vladimir Sementsov-Ogievskiy |
Subject: |
Re: [PATCH for-5.0 v2 06/23] block: Add bdrv_recurse_can_replace() |
Date: |
Fri, 29 Nov 2019 11:04:51 +0000 |
29.11.2019 13:23, Max Reitz wrote:
> On 29.11.19 10:34, Vladimir Sementsov-Ogievskiy wrote:
>> 11.11.2019 19:01, Max Reitz wrote:
>>> After a couple of follow-up patches, this function will replace
>>> bdrv_recurse_is_first_non_filter() in check_to_replace_node().
>>>
>>> bdrv_recurse_is_first_non_filter() is both not sufficiently specific for
>>> check_to_replace_node() (it allows cases that should not be allowed,
>>> like replacing child nodes of quorum with dissenting data that have more
>>> parents than just quorum), and it is too restrictive (it is perfectly
>>> fine to replace filters).
>>>
>>> Signed-off-by: Max Reitz <address@hidden>
>>> ---
>>> block.c | 38 ++++++++++++++++++++++++++++++++++++++
>>> include/block/block_int.h | 10 ++++++++++
>>> 2 files changed, 48 insertions(+)
>>>
>>> diff --git a/block.c b/block.c
>>> index 9b1049786a..de53addeb0 100644
>>> --- a/block.c
>>> +++ b/block.c
>>> @@ -6205,6 +6205,44 @@ bool
>>> bdrv_recurse_is_first_non_filter(BlockDriverState *bs,
>>> return false;
>>> }
>>>
>>> +/*
>>> + * This function checks whether the given @to_replace is allowed to be
>>> + * replaced by a node that always shows the same data as @bs. This is
>>> + * used for example to verify whether the mirror job can replace
>>> + * @to_replace by the target mirrored from @bs.
>>> + * To be replaceable, @bs and @to_replace may either be guaranteed to
>>> + * always show the same data (because they are only connected through
>>> + * filters), or some driver may allow replacing one of its children
>>> + * because it can guarantee that this child's data is not visible at
>>> + * all (for example, for dissenting quorum children that have no other
>>> + * parents).
>>> + */
>>> +bool bdrv_recurse_can_replace(BlockDriverState *bs,
>>> + BlockDriverState *to_replace)
>>> +{
>>> + if (!bs || !bs->drv) {
>>> + return false;
>>> + }
>>> +
>>> + if (bs == to_replace) {
>>> + return true;
>>> + }
>>> +
>>> + /* See what the driver can do */
>>> + if (bs->drv->bdrv_recurse_can_replace) {
>>> + return bs->drv->bdrv_recurse_can_replace(bs, to_replace);
>>> + }
>>> +
>>> + /* For filters without an own implementation, we can recurse on our
>>> own */
>>> + if (bs->drv->is_filter) {
>>> + BdrvChild *child = bs->file ?: bs->backing;
>>
>> should we check that child != NULL ?
>
> I’d say that normally (once they are open) filters must have a child,
> and so I’d make it an assertion. But then again an assertion isn’t much
> better than the dereferencing that follows, I think. :?
>
> Max
OK then.
Reviewed-by: Vladimir Sementsov-Ogievskiy <address@hidden>
>
>>> + return bdrv_recurse_can_replace(child->bs, to_replace);
>>> + }
>>> +
>>> + /* Safe default */
>>> + return false;
>>> +}
>>> +
>>> BlockDriverState *check_to_replace_node(BlockDriverState *parent_bs,
>>> const char *node_name, Error
>>> **errp)
>>> {
>>> diff --git a/include/block/block_int.h b/include/block/block_int.h
>>> index dd033d0b37..75f03dcc38 100644
>>> --- a/include/block/block_int.h
>>> +++ b/include/block/block_int.h
>>> @@ -102,6 +102,13 @@ struct BlockDriver {
>>> */
>>> bool (*bdrv_recurse_is_first_non_filter)(BlockDriverState *bs,
>>> BlockDriverState
>>> *candidate);
>>> + /*
>>> + * Return true if @to_replace can be replaced by a BDS with the
>>> + * same data as @bs without it affecting @bs's behavior (that is,
>>> + * without it being visible to @bs's parents).
>>> + */
>>> + bool (*bdrv_recurse_can_replace)(BlockDriverState *bs,
>>> + BlockDriverState *to_replace);
>>>
>>> int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char
>>> *filename);
>>> int (*bdrv_probe_device)(const char *filename);
>>> @@ -1264,6 +1271,9 @@ void bdrv_format_default_perms(BlockDriverState *bs,
>>> BdrvChild *c,
>>> uint64_t perm, uint64_t shared,
>>> uint64_t *nperm, uint64_t *nshared);
>>>
>>> +bool bdrv_recurse_can_replace(BlockDriverState *bs,
>>> + BlockDriverState *to_replace);
>>> +
>>> /*
>>> * Default implementation for drivers to pass bdrv_co_block_status() to
>>> * their file.
>>>
>>
>>
>
>
--
Best regards,
Vladimir
- [PATCH for-5.0 v2 00/23] block: Fix check_to_replace_node(), Max Reitz, 2019/11/11
- [PATCH for-5.0 v2 01/23] blockdev: Allow external snapshots everywhere, Max Reitz, 2019/11/11
- [PATCH for-5.0 v2 02/23] blockdev: Allow resizing everywhere, Max Reitz, 2019/11/11
- [PATCH for-5.0 v2 03/23] block: Drop bdrv_is_first_non_filter(), Max Reitz, 2019/11/11
- [PATCH for-5.0 v2 04/23] iotests: Let 041 use -blockdev for quorum children, Max Reitz, 2019/11/11
- [PATCH for-5.0 v2 05/23] quorum: Fix child permissions, Max Reitz, 2019/11/11
- [PATCH for-5.0 v2 06/23] block: Add bdrv_recurse_can_replace(), Max Reitz, 2019/11/11
- [PATCH for-5.0 v2 07/23] blkverify: Implement .bdrv_recurse_can_replace(), Max Reitz, 2019/11/11
- [PATCH for-5.0 v2 08/23] quorum: Store children in own structure, Max Reitz, 2019/11/11
- [PATCH for-5.0 v2 09/23] quorum: Add QuorumChild.to_be_replaced, Max Reitz, 2019/11/11
- [PATCH for-5.0 v2 10/23] quorum: Implement .bdrv_recurse_can_replace(), Max Reitz, 2019/11/11
- [PATCH for-5.0 v2 11/23] block: Use bdrv_recurse_can_replace(), Max Reitz, 2019/11/11