Re: [Qemu-block] [PATCH v6 14/42] block: Use CAFs when working with backing chains

2019-09-09 Thread Max Reitz
On 09.09.19 11:55, Kevin Wolf wrote:
> Am 09.09.2019 um 10:25 hat Max Reitz geschrieben:
>> On 05.09.19 16:05, Kevin Wolf wrote:
>>> Am 09.08.2019 um 18:13 hat Max Reitz geschrieben:
 Use child access functions when iterating through backing chains so
 filters do not break the chain.

 Signed-off-by: Max Reitz 
 ---
  block.c | 40 
  1 file changed, 28 insertions(+), 12 deletions(-)

 diff --git a/block.c b/block.c
 index 86b84bea21..42abbaf0ba 100644
 --- a/block.c
 +++ b/block.c
 @@ -4376,7 +4376,8 @@ int bdrv_change_backing_file(BlockDriverState *bs,
  }
  
  /*
 - * Finds the image layer in the chain that has 'bs' as its backing file.
 + * Finds the image layer in the chain that has 'bs' (or a filter on
 + * top of it) as its backing file.
   *
   * active is the current topmost image.
   *
 @@ -4388,11 +4389,18 @@ int bdrv_change_backing_file(BlockDriverState *bs,
  BlockDriverState *bdrv_find_overlay(BlockDriverState *active,
  BlockDriverState *bs)
  {
 -while (active && bs != backing_bs(active)) {
 -active = backing_bs(active);
 +bs = bdrv_skip_rw_filters(bs);
 +active = bdrv_skip_rw_filters(active);
>>>
>>> This does more than the commit message says. In addition to iterating
>>> through filters instead of stopping, it also changes the semantics of
>>> the function to return the next non-filter on top of bs instead of the
>>> next node.
>>
>> Which is to say the overlay.
>>
>> (I think we only ever use “overlay” in the COW sense.)
> 
> I think we do, but so far also only ever for immediate COW childs, not
> for skipping through intermediate node.

Yes, because it’s broken so far.

>>> The block jobs seem to use it only for bdrv_is_allocated_above(), which
>>> should return the same thing in both cases, so the behaviour stays the
>>> same. qmp_block_commit() will check op blockers on a different node now,
>>> which could be a fix or a bug, I can't tell offhand. Probably the
>>> blocking doesn't really work anyway.
>>
>> You mean that the op blocker could have been on a block job filter node
>> before?  I think that‘s pretty much the point of this fix; that that
>> doesn’t make sense.  (We didn’t have mirror_top_bs and the like at
>> 058223a6e3b.)
> 
> On the off chance that the op blocker actually works, it can't be a job
> filter. I was thinking more of throttling, blkdebug etc.

Well, that’s just broken altogether right now.

>>> All of this should be mentioned in the commit message at least. Maybe
>>> it's also worth splitting in two patches.
>>
>> I don’t know.  The function was written when there were no filters.
> 
> I doubt it. blkdebug is a really old filter.
> 
>> This change would have been a no-op then.  The fact that it isn’t to me
>> just means that introducing filters broke it.
>>
>> So I don’t know what I would write.  Maybe “bdrv_find_overlay() now
>> actually finds the overlay, that is, it will not return a filter node.
>> This is the behavior that all callers expect (because they work on COW
>> backing chains).”
> 
> Maybe just something like "In addition, filter nodes are not returned as
> overlays any more. Instead, the first non-filter node on top of bs is
> considered the overlay now."?

Isn’t that basically the same? :-)

Max



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-block] [PATCH v6 14/42] block: Use CAFs when working with backing chains

2019-09-09 Thread Kevin Wolf
Am 09.09.2019 um 10:25 hat Max Reitz geschrieben:
> On 05.09.19 16:05, Kevin Wolf wrote:
> > Am 09.08.2019 um 18:13 hat Max Reitz geschrieben:
> >> Use child access functions when iterating through backing chains so
> >> filters do not break the chain.
> >>
> >> Signed-off-by: Max Reitz 
> >> ---
> >>  block.c | 40 
> >>  1 file changed, 28 insertions(+), 12 deletions(-)
> >>
> >> diff --git a/block.c b/block.c
> >> index 86b84bea21..42abbaf0ba 100644
> >> --- a/block.c
> >> +++ b/block.c
> >> @@ -4376,7 +4376,8 @@ int bdrv_change_backing_file(BlockDriverState *bs,
> >>  }
> >>  
> >>  /*
> >> - * Finds the image layer in the chain that has 'bs' as its backing file.
> >> + * Finds the image layer in the chain that has 'bs' (or a filter on
> >> + * top of it) as its backing file.
> >>   *
> >>   * active is the current topmost image.
> >>   *
> >> @@ -4388,11 +4389,18 @@ int bdrv_change_backing_file(BlockDriverState *bs,
> >>  BlockDriverState *bdrv_find_overlay(BlockDriverState *active,
> >>  BlockDriverState *bs)
> >>  {
> >> -while (active && bs != backing_bs(active)) {
> >> -active = backing_bs(active);
> >> +bs = bdrv_skip_rw_filters(bs);
> >> +active = bdrv_skip_rw_filters(active);
> > 
> > This does more than the commit message says. In addition to iterating
> > through filters instead of stopping, it also changes the semantics of
> > the function to return the next non-filter on top of bs instead of the
> > next node.
> 
> Which is to say the overlay.
> 
> (I think we only ever use “overlay” in the COW sense.)

I think we do, but so far also only ever for immediate COW childs, not
for skipping through intermediate node.

> > The block jobs seem to use it only for bdrv_is_allocated_above(), which
> > should return the same thing in both cases, so the behaviour stays the
> > same. qmp_block_commit() will check op blockers on a different node now,
> > which could be a fix or a bug, I can't tell offhand. Probably the
> > blocking doesn't really work anyway.
> 
> You mean that the op blocker could have been on a block job filter node
> before?  I think that‘s pretty much the point of this fix; that that
> doesn’t make sense.  (We didn’t have mirror_top_bs and the like at
> 058223a6e3b.)

On the off chance that the op blocker actually works, it can't be a job
filter. I was thinking more of throttling, blkdebug etc.

> > All of this should be mentioned in the commit message at least. Maybe
> > it's also worth splitting in two patches.
> 
> I don’t know.  The function was written when there were no filters.

I doubt it. blkdebug is a really old filter.

> This change would have been a no-op then.  The fact that it isn’t to me
> just means that introducing filters broke it.
> 
> So I don’t know what I would write.  Maybe “bdrv_find_overlay() now
> actually finds the overlay, that is, it will not return a filter node.
> This is the behavior that all callers expect (because they work on COW
> backing chains).”

Maybe just something like "In addition, filter nodes are not returned as
overlays any more. Instead, the first non-filter node on top of bs is
considered the overlay now."?

Kevin


signature.asc
Description: PGP signature


Re: [Qemu-block] [PATCH v6 14/42] block: Use CAFs when working with backing chains

2019-09-09 Thread Max Reitz
On 05.09.19 16:05, Kevin Wolf wrote:
> Am 09.08.2019 um 18:13 hat Max Reitz geschrieben:
>> Use child access functions when iterating through backing chains so
>> filters do not break the chain.
>>
>> Signed-off-by: Max Reitz 
>> ---
>>  block.c | 40 
>>  1 file changed, 28 insertions(+), 12 deletions(-)
>>
>> diff --git a/block.c b/block.c
>> index 86b84bea21..42abbaf0ba 100644
>> --- a/block.c
>> +++ b/block.c
>> @@ -4376,7 +4376,8 @@ int bdrv_change_backing_file(BlockDriverState *bs,
>>  }
>>  
>>  /*
>> - * Finds the image layer in the chain that has 'bs' as its backing file.
>> + * Finds the image layer in the chain that has 'bs' (or a filter on
>> + * top of it) as its backing file.
>>   *
>>   * active is the current topmost image.
>>   *
>> @@ -4388,11 +4389,18 @@ int bdrv_change_backing_file(BlockDriverState *bs,
>>  BlockDriverState *bdrv_find_overlay(BlockDriverState *active,
>>  BlockDriverState *bs)
>>  {
>> -while (active && bs != backing_bs(active)) {
>> -active = backing_bs(active);
>> +bs = bdrv_skip_rw_filters(bs);
>> +active = bdrv_skip_rw_filters(active);
> 
> This does more than the commit message says. In addition to iterating
> through filters instead of stopping, it also changes the semantics of
> the function to return the next non-filter on top of bs instead of the
> next node.

Which is to say the overlay.

(I think we only ever use “overlay” in the COW sense.)

> The block jobs seem to use it only for bdrv_is_allocated_above(), which
> should return the same thing in both cases, so the behaviour stays the
> same. qmp_block_commit() will check op blockers on a different node now,
> which could be a fix or a bug, I can't tell offhand. Probably the
> blocking doesn't really work anyway.

You mean that the op blocker could have been on a block job filter node
before?  I think that‘s pretty much the point of this fix; that that
doesn’t make sense.  (We didn’t have mirror_top_bs and the like at
058223a6e3b.)

> All of this should be mentioned in the commit message at least. Maybe
> it's also worth splitting in two patches.

I don’t know.  The function was written when there were no filters.
This change would have been a no-op then.  The fact that it isn’t to me
just means that introducing filters broke it.

So I don’t know what I would write.  Maybe “bdrv_find_overlay() now
actually finds the overlay, that is, it will not return a filter node.
This is the behavior that all callers expect (because they work on COW
backing chains).”

>> +while (active) {
>> +BlockDriverState *next = bdrv_backing_chain_next(active);
>> +if (bs == next) {
>> +return active;
>> +}
>> +active = next;
>>  }
>>  
>> -return active;
>> +return NULL;
>>  }
>>  
>>  /* Given a BDS, searches for the base layer. */
>> @@ -4544,9 +4552,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, 
>> BlockDriverState *base,
>>   * other intermediate nodes have been dropped.
>>   * If 'top' is an implicit node (e.g. "commit_top") we should skip
>>   * it because no one inherits from it. We use explicit_top for that. */
>> -while (explicit_top && explicit_top->implicit) {
>> -explicit_top = backing_bs(explicit_top);
>> -}
>> +explicit_top = bdrv_skip_implicit_filters(explicit_top);
>>  update_inherits_from = bdrv_inherits_from_recursive(base, explicit_top);
>>  
>>  /* success - we can delete the intermediate states, and link top->base 
>> */
>> @@ -5014,7 +5020,7 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
>>  bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base)
>>  {
>>  while (top && top != base) {
>> -top = backing_bs(top);
>> +top = bdrv_filtered_bs(top);
>>  }
>>  
>>  return top != NULL;
>> @@ -5253,7 +5259,17 @@ BlockDriverState 
>> *bdrv_find_backing_image(BlockDriverState *bs,
>>  
>>  is_protocol = path_has_protocol(backing_file);
>>  
>> -for (curr_bs = bs; curr_bs->backing; curr_bs = curr_bs->backing->bs) {
>> +/*
>> + * Being largely a legacy function, skip any filters here
>> + * (because filters do not have normal filenames, so they cannot
>> + * match anyway; and allowing json:{} filenames is a bit out of
>> + * scope).
>> + */
>> +for (curr_bs = bdrv_skip_rw_filters(bs);
>> + bdrv_filtered_cow_child(curr_bs) != NULL;
>> + curr_bs = bdrv_backing_chain_next(curr_bs))
> 
> This could just use bs_below instead of recalculating the node if you
> moved the declaration of bs_below to the function scope.

Indeed, thanks.

Max

>> +{
>> +BlockDriverState *bs_below = bdrv_backing_chain_next(curr_bs);
>>  
>>  /* If either of the filename paths is actually a protocol, then
>>   * compare unmodified paths; otherwise make paths relative */



signature.asc
Description: OpenPGP digital signa

Re: [Qemu-block] [PATCH v6 14/42] block: Use CAFs when working with backing chains

2019-09-05 Thread Kevin Wolf
Am 09.08.2019 um 18:13 hat Max Reitz geschrieben:
> Use child access functions when iterating through backing chains so
> filters do not break the chain.
> 
> Signed-off-by: Max Reitz 
> ---
>  block.c | 40 
>  1 file changed, 28 insertions(+), 12 deletions(-)
> 
> diff --git a/block.c b/block.c
> index 86b84bea21..42abbaf0ba 100644
> --- a/block.c
> +++ b/block.c
> @@ -4376,7 +4376,8 @@ int bdrv_change_backing_file(BlockDriverState *bs,
>  }
>  
>  /*
> - * Finds the image layer in the chain that has 'bs' as its backing file.
> + * Finds the image layer in the chain that has 'bs' (or a filter on
> + * top of it) as its backing file.
>   *
>   * active is the current topmost image.
>   *
> @@ -4388,11 +4389,18 @@ int bdrv_change_backing_file(BlockDriverState *bs,
>  BlockDriverState *bdrv_find_overlay(BlockDriverState *active,
>  BlockDriverState *bs)
>  {
> -while (active && bs != backing_bs(active)) {
> -active = backing_bs(active);
> +bs = bdrv_skip_rw_filters(bs);
> +active = bdrv_skip_rw_filters(active);

This does more than the commit message says. In addition to iterating
through filters instead of stopping, it also changes the semantics of
the function to return the next non-filter on top of bs instead of the
next node.

The block jobs seem to use it only for bdrv_is_allocated_above(), which
should return the same thing in both cases, so the behaviour stays the
same. qmp_block_commit() will check op blockers on a different node now,
which could be a fix or a bug, I can't tell offhand. Probably the
blocking doesn't really work anyway.

All of this should be mentioned in the commit message at least. Maybe
it's also worth splitting in two patches.

> +while (active) {
> +BlockDriverState *next = bdrv_backing_chain_next(active);
> +if (bs == next) {
> +return active;
> +}
> +active = next;
>  }
>  
> -return active;
> +return NULL;
>  }
>  
>  /* Given a BDS, searches for the base layer. */
> @@ -4544,9 +4552,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, 
> BlockDriverState *base,
>   * other intermediate nodes have been dropped.
>   * If 'top' is an implicit node (e.g. "commit_top") we should skip
>   * it because no one inherits from it. We use explicit_top for that. */
> -while (explicit_top && explicit_top->implicit) {
> -explicit_top = backing_bs(explicit_top);
> -}
> +explicit_top = bdrv_skip_implicit_filters(explicit_top);
>  update_inherits_from = bdrv_inherits_from_recursive(base, explicit_top);
>  
>  /* success - we can delete the intermediate states, and link top->base */
> @@ -5014,7 +5020,7 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
>  bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base)
>  {
>  while (top && top != base) {
> -top = backing_bs(top);
> +top = bdrv_filtered_bs(top);
>  }
>  
>  return top != NULL;
> @@ -5253,7 +5259,17 @@ BlockDriverState 
> *bdrv_find_backing_image(BlockDriverState *bs,
>  
>  is_protocol = path_has_protocol(backing_file);
>  
> -for (curr_bs = bs; curr_bs->backing; curr_bs = curr_bs->backing->bs) {
> +/*
> + * Being largely a legacy function, skip any filters here
> + * (because filters do not have normal filenames, so they cannot
> + * match anyway; and allowing json:{} filenames is a bit out of
> + * scope).
> + */
> +for (curr_bs = bdrv_skip_rw_filters(bs);
> + bdrv_filtered_cow_child(curr_bs) != NULL;
> + curr_bs = bdrv_backing_chain_next(curr_bs))

This could just use bs_below instead of recalculating the node if you
moved the declaration of bs_below to the function scope.

> +{
> +BlockDriverState *bs_below = bdrv_backing_chain_next(curr_bs);
>  
>  /* If either of the filename paths is actually a protocol, then
>   * compare unmodified paths; otherwise make paths relative */
> @@ -5261,7 +5277,7 @@ BlockDriverState 
> *bdrv_find_backing_image(BlockDriverState *bs,
>  char *backing_file_full_ret;
>  
>  if (strcmp(backing_file, curr_bs->backing_file) == 0) {
> -retval = curr_bs->backing->bs;
> +retval = bs_below;
>  break;
>  }
>  /* Also check against the full backing filename for the image */
> @@ -5271,7 +5287,7 @@ BlockDriverState 
> *bdrv_find_backing_image(BlockDriverState *bs,
>  bool equal = strcmp(backing_file, backing_file_full_ret) == 
> 0;
>  g_free(backing_file_full_ret);
>  if (equal) {
> -retval = curr_bs->backing->bs;
> +retval = bs_below;
>  break;
>  }
>  }
> @@ -5297,7 +5313,7 @@ BlockDriverState 
> *bdrv_find_backing_image(BlockDriverState *bs,
>  g_fr

Re: [Qemu-block] [PATCH v6 14/42] block: Use CAFs when working with backing chains

2019-08-10 Thread Vladimir Sementsov-Ogievskiy
09.08.2019 19:13, Max Reitz wrote:
> Use child access functions when iterating through backing chains so
> filters do not break the chain.
> 
> Signed-off-by: Max Reitz 

Reviewed-by: Vladimir Sementsov-Ogievskiy 


-- 
Best regards,
Vladimir


[Qemu-block] [PATCH v6 14/42] block: Use CAFs when working with backing chains

2019-08-09 Thread Max Reitz
Use child access functions when iterating through backing chains so
filters do not break the chain.

Signed-off-by: Max Reitz 
---
 block.c | 40 
 1 file changed, 28 insertions(+), 12 deletions(-)

diff --git a/block.c b/block.c
index 86b84bea21..42abbaf0ba 100644
--- a/block.c
+++ b/block.c
@@ -4376,7 +4376,8 @@ int bdrv_change_backing_file(BlockDriverState *bs,
 }
 
 /*
- * Finds the image layer in the chain that has 'bs' as its backing file.
+ * Finds the image layer in the chain that has 'bs' (or a filter on
+ * top of it) as its backing file.
  *
  * active is the current topmost image.
  *
@@ -4388,11 +4389,18 @@ int bdrv_change_backing_file(BlockDriverState *bs,
 BlockDriverState *bdrv_find_overlay(BlockDriverState *active,
 BlockDriverState *bs)
 {
-while (active && bs != backing_bs(active)) {
-active = backing_bs(active);
+bs = bdrv_skip_rw_filters(bs);
+active = bdrv_skip_rw_filters(active);
+
+while (active) {
+BlockDriverState *next = bdrv_backing_chain_next(active);
+if (bs == next) {
+return active;
+}
+active = next;
 }
 
-return active;
+return NULL;
 }
 
 /* Given a BDS, searches for the base layer. */
@@ -4544,9 +4552,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, 
BlockDriverState *base,
  * other intermediate nodes have been dropped.
  * If 'top' is an implicit node (e.g. "commit_top") we should skip
  * it because no one inherits from it. We use explicit_top for that. */
-while (explicit_top && explicit_top->implicit) {
-explicit_top = backing_bs(explicit_top);
-}
+explicit_top = bdrv_skip_implicit_filters(explicit_top);
 update_inherits_from = bdrv_inherits_from_recursive(base, explicit_top);
 
 /* success - we can delete the intermediate states, and link top->base */
@@ -5014,7 +5020,7 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
 bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base)
 {
 while (top && top != base) {
-top = backing_bs(top);
+top = bdrv_filtered_bs(top);
 }
 
 return top != NULL;
@@ -5253,7 +5259,17 @@ BlockDriverState 
*bdrv_find_backing_image(BlockDriverState *bs,
 
 is_protocol = path_has_protocol(backing_file);
 
-for (curr_bs = bs; curr_bs->backing; curr_bs = curr_bs->backing->bs) {
+/*
+ * Being largely a legacy function, skip any filters here
+ * (because filters do not have normal filenames, so they cannot
+ * match anyway; and allowing json:{} filenames is a bit out of
+ * scope).
+ */
+for (curr_bs = bdrv_skip_rw_filters(bs);
+ bdrv_filtered_cow_child(curr_bs) != NULL;
+ curr_bs = bdrv_backing_chain_next(curr_bs))
+{
+BlockDriverState *bs_below = bdrv_backing_chain_next(curr_bs);
 
 /* If either of the filename paths is actually a protocol, then
  * compare unmodified paths; otherwise make paths relative */
@@ -5261,7 +5277,7 @@ BlockDriverState 
*bdrv_find_backing_image(BlockDriverState *bs,
 char *backing_file_full_ret;
 
 if (strcmp(backing_file, curr_bs->backing_file) == 0) {
-retval = curr_bs->backing->bs;
+retval = bs_below;
 break;
 }
 /* Also check against the full backing filename for the image */
@@ -5271,7 +5287,7 @@ BlockDriverState 
*bdrv_find_backing_image(BlockDriverState *bs,
 bool equal = strcmp(backing_file, backing_file_full_ret) == 0;
 g_free(backing_file_full_ret);
 if (equal) {
-retval = curr_bs->backing->bs;
+retval = bs_below;
 break;
 }
 }
@@ -5297,7 +5313,7 @@ BlockDriverState 
*bdrv_find_backing_image(BlockDriverState *bs,
 g_free(filename_tmp);
 
 if (strcmp(backing_file_full, filename_full) == 0) {
-retval = curr_bs->backing->bs;
+retval = bs_below;
 break;
 }
 }
-- 
2.21.0