Re: [Qemu-block] [PATCH v6 14/42] block: Use CAFs when working with backing chains
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
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
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
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
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
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