* [PATCH] btrfs: fix backref walking not returning all inode refs
@ 2023-05-03 14:27 fdmanana
2023-05-04 9:41 ` Wang Yugui
2023-05-04 10:12 ` [PATCH v2] " fdmanana
0 siblings, 2 replies; 7+ messages in thread
From: fdmanana @ 2023-05-03 14:27 UTC (permalink / raw)
To: linux-btrfs; +Cc: git, Filipe Manana, stable
From: Filipe Manana <fdmanana@suse.com>
When using the logical to ino ioctl v2, if the flag to ignore offsets of
file extent items (BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET) is given, the
backref walking code ends up not returning references for all file offsets
of an inode that point to the given logical bytenr. This happens since
kernel 6.2, commit 6ce6ba534418 ("btrfs: use a single argument for extent
offset in backref walking functions"), as it mistakenly skipped the search
for file extent items in a leaf that point to the target extent if that
flag is given. Instead it should only skip the filtering done by
check_extent_in_eb() - that is, it should not avoid the calls to that
function.
So fix this by always calling check_extent_in_eb() and have this function
do the filtering only if an extent offset is given and the flag to ignore
offsets is not set.
Fixes: 6ce6ba534418 ("btrfs: use a single argument for extent offset in backref walking functions")
Reported-by: Vladimir Panteleev <git@vladimir.panteleev.md>
Link: https://lore.kernel.org/linux-btrfs/CAHhfkvwo=nmzrJSqZ2qMfF-rZB-ab6ahHnCD_sq9h4o8v+M7QQ@mail.gmail.com/
Tested-by: Vladimir Panteleev <git@vladimir.panteleev.md>
CC: stable@vger.kernel.org # 6.2+
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
fs/btrfs/backref.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index e54f0884802a..8e61be3fe9a8 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -45,7 +45,9 @@ static int check_extent_in_eb(struct btrfs_backref_walk_ctx *ctx,
int root_count;
bool cached;
- if (!btrfs_file_extent_compression(eb, fi) &&
+ if (!ctx->ignore_extent_item_pos &&
+ ctx->extent_item_pos > 0 &&
+ !btrfs_file_extent_compression(eb, fi) &&
!btrfs_file_extent_encryption(eb, fi) &&
!btrfs_file_extent_other_encoding(eb, fi)) {
u64 data_offset;
@@ -552,13 +554,10 @@ static int add_all_parents(struct btrfs_backref_walk_ctx *ctx,
count++;
else
goto next;
- if (!ctx->ignore_extent_item_pos) {
- ret = check_extent_in_eb(ctx, &key, eb, fi, &eie);
- if (ret == BTRFS_ITERATE_EXTENT_INODES_STOP ||
- ret < 0)
- break;
- }
- if (ret > 0)
+ ret = check_extent_in_eb(ctx, &key, eb, fi, &eie);
+ if (ret == BTRFS_ITERATE_EXTENT_INODES_STOP || ret < 0)
+ break;
+ else if (ret > 0)
goto next;
ret = ulist_add_merge_ptr(parents, eb->start,
eie, (void **)&old, GFP_NOFS);
--
2.35.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] btrfs: fix backref walking not returning all inode refs
2023-05-03 14:27 [PATCH] btrfs: fix backref walking not returning all inode refs fdmanana
@ 2023-05-04 9:41 ` Wang Yugui
2023-05-04 10:13 ` Filipe Manana
2023-05-04 10:12 ` [PATCH v2] " fdmanana
1 sibling, 1 reply; 7+ messages in thread
From: Wang Yugui @ 2023-05-04 9:41 UTC (permalink / raw)
To: fdmanana; +Cc: linux-btrfs, git, Filipe Manana, stable
Hi,
> From: Filipe Manana <fdmanana@suse.com>
>
> When using the logical to ino ioctl v2, if the flag to ignore offsets of
> file extent items (BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET) is given, the
> backref walking code ends up not returning references for all file offsets
> of an inode that point to the given logical bytenr. This happens since
> kernel 6.2, commit 6ce6ba534418 ("btrfs: use a single argument for extent
> offset in backref walking functions"), as it mistakenly skipped the search
> for file extent items in a leaf that point to the target extent if that
> flag is given. Instead it should only skip the filtering done by
> check_extent_in_eb() - that is, it should not avoid the calls to that
> function.
>
> So fix this by always calling check_extent_in_eb() and have this function
> do the filtering only if an extent offset is given and the flag to ignore
> offsets is not set.
> Fixes: 6ce6ba534418 ("btrfs: use a single argument for extent offset in backref walking functions")
> Reported-by: Vladimir Panteleev <git@vladimir.panteleev.md>
> Link: https://lore.kernel.org/linux-btrfs/CAHhfkvwo=nmzrJSqZ2qMfF-rZB-ab6ahHnCD_sq9h4o8v+M7QQ@mail.gmail.com/
> Tested-by: Vladimir Panteleev <git@vladimir.panteleev.md>
> CC: stable@vger.kernel.org # 6.2+
> Signed-off-by: Filipe Manana <fdmanana@suse.com>
fstests(btrfs/299) will fail with this patch.
Best Regards
Wang Yugui (wangyugui@e16-tech.com)
2023/05/04
> ---
> fs/btrfs/backref.c | 15 +++++++--------
> 1 file changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
> index e54f0884802a..8e61be3fe9a8 100644
> --- a/fs/btrfs/backref.c
> +++ b/fs/btrfs/backref.c
> @@ -45,7 +45,9 @@ static int check_extent_in_eb(struct btrfs_backref_walk_ctx *ctx,
> int root_count;
> bool cached;
>
> - if (!btrfs_file_extent_compression(eb, fi) &&
> + if (!ctx->ignore_extent_item_pos &&
> + ctx->extent_item_pos > 0 &&
> + !btrfs_file_extent_compression(eb, fi) &&
> !btrfs_file_extent_encryption(eb, fi) &&
> !btrfs_file_extent_other_encoding(eb, fi)) {
> u64 data_offset;
> @@ -552,13 +554,10 @@ static int add_all_parents(struct btrfs_backref_walk_ctx *ctx,
> count++;
> else
> goto next;
> - if (!ctx->ignore_extent_item_pos) {
> - ret = check_extent_in_eb(ctx, &key, eb, fi, &eie);
> - if (ret == BTRFS_ITERATE_EXTENT_INODES_STOP ||
> - ret < 0)
> - break;
> - }
> - if (ret > 0)
> + ret = check_extent_in_eb(ctx, &key, eb, fi, &eie);
> + if (ret == BTRFS_ITERATE_EXTENT_INODES_STOP || ret < 0)
> + break;
> + else if (ret > 0)
> goto next;
> ret = ulist_add_merge_ptr(parents, eb->start,
> eie, (void **)&old, GFP_NOFS);
> --
> 2.35.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2] btrfs: fix backref walking not returning all inode refs
2023-05-03 14:27 [PATCH] btrfs: fix backref walking not returning all inode refs fdmanana
2023-05-04 9:41 ` Wang Yugui
@ 2023-05-04 10:12 ` fdmanana
2023-05-05 10:03 ` David Sterba
1 sibling, 1 reply; 7+ messages in thread
From: fdmanana @ 2023-05-04 10:12 UTC (permalink / raw)
To: linux-btrfs; +Cc: git, Filipe Manana, stable
From: Filipe Manana <fdmanana@suse.com>
When using the logical to ino ioctl v2, if the flag to ignore offsets of
file extent items (BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET) is given, the
backref walking code ends up not returning references for all file offsets
of an inode that point to the given logical bytenr. This happens since
kernel 6.2, commit 6ce6ba534418 ("btrfs: use a single argument for extent
offset in backref walking functions"), as it mistakenly skipped the search
for file extent items in a leaf that point to the target extent if that
flag is given. Instead it should only skip the filtering done by
check_extent_in_eb() - that is, it should not avoid the calls to that
function (or find_extent_in_eb(), which uses it).
So fix this by always calling check_extent_in_eb() and find_extent_in_eb()
and have check_extent_in_eb() do the filtering only if the flag to ignore
offsets is set.
Fixes: 6ce6ba534418 ("btrfs: use a single argument for extent offset in backref walking functions")
Reported-by: Vladimir Panteleev <git@vladimir.panteleev.md>
Link: https://lore.kernel.org/linux-btrfs/CAHhfkvwo=nmzrJSqZ2qMfF-rZB-ab6ahHnCD_sq9h4o8v+M7QQ@mail.gmail.com/
Tested-by: Vladimir Panteleev <git@vladimir.panteleev.md>
CC: stable@vger.kernel.org # 6.2+
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
V2: Remove wrong check for a non-zero extent item offset.
Apply the same logic at find_parent_nodes(), that is, search for file
extent items on a leaf if the ignore flag is given - the filtering
will be done later at check_extent_in_eb(). Spotted by Vladimir Panteleev
in the thread mentioned above.
fs/btrfs/backref.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index e54f0884802a..787417f9893c 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -45,7 +45,8 @@ static int check_extent_in_eb(struct btrfs_backref_walk_ctx *ctx,
int root_count;
bool cached;
- if (!btrfs_file_extent_compression(eb, fi) &&
+ if (!ctx->ignore_extent_item_pos &&
+ !btrfs_file_extent_compression(eb, fi) &&
!btrfs_file_extent_encryption(eb, fi) &&
!btrfs_file_extent_other_encoding(eb, fi)) {
u64 data_offset;
@@ -552,13 +553,10 @@ static int add_all_parents(struct btrfs_backref_walk_ctx *ctx,
count++;
else
goto next;
- if (!ctx->ignore_extent_item_pos) {
- ret = check_extent_in_eb(ctx, &key, eb, fi, &eie);
- if (ret == BTRFS_ITERATE_EXTENT_INODES_STOP ||
- ret < 0)
- break;
- }
- if (ret > 0)
+ ret = check_extent_in_eb(ctx, &key, eb, fi, &eie);
+ if (ret == BTRFS_ITERATE_EXTENT_INODES_STOP || ret < 0)
+ break;
+ else if (ret > 0)
goto next;
ret = ulist_add_merge_ptr(parents, eb->start,
eie, (void **)&old, GFP_NOFS);
@@ -1606,8 +1604,7 @@ static int find_parent_nodes(struct btrfs_backref_walk_ctx *ctx,
goto out;
}
if (ref->count && ref->parent) {
- if (!ctx->ignore_extent_item_pos && !ref->inode_list &&
- ref->level == 0) {
+ if (!ref->inode_list && ref->level == 0) {
struct btrfs_tree_parent_check check = { 0 };
struct extent_buffer *eb;
--
2.35.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] btrfs: fix backref walking not returning all inode refs
2023-05-04 9:41 ` Wang Yugui
@ 2023-05-04 10:13 ` Filipe Manana
0 siblings, 0 replies; 7+ messages in thread
From: Filipe Manana @ 2023-05-04 10:13 UTC (permalink / raw)
To: Wang Yugui; +Cc: linux-btrfs, git, Filipe Manana, stable
On Thu, May 4, 2023 at 10:41 AM Wang Yugui <wangyugui@e16-tech.com> wrote:
>
> Hi,
>
> > From: Filipe Manana <fdmanana@suse.com>
> >
> > When using the logical to ino ioctl v2, if the flag to ignore offsets of
> > file extent items (BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET) is given, the
> > backref walking code ends up not returning references for all file offsets
> > of an inode that point to the given logical bytenr. This happens since
> > kernel 6.2, commit 6ce6ba534418 ("btrfs: use a single argument for extent
> > offset in backref walking functions"), as it mistakenly skipped the search
> > for file extent items in a leaf that point to the target extent if that
> > flag is given. Instead it should only skip the filtering done by
> > check_extent_in_eb() - that is, it should not avoid the calls to that
> > function.
> >
> > So fix this by always calling check_extent_in_eb() and have this function
> > do the filtering only if an extent offset is given and the flag to ignore
> > offsets is not set.
> > Fixes: 6ce6ba534418 ("btrfs: use a single argument for extent offset in backref walking functions")
> > Reported-by: Vladimir Panteleev <git@vladimir.panteleev.md>
> > Link: https://lore.kernel.org/linux-btrfs/CAHhfkvwo=nmzrJSqZ2qMfF-rZB-ab6ahHnCD_sq9h4o8v+M7QQ@mail.gmail.com/
> > Tested-by: Vladimir Panteleev <git@vladimir.panteleev.md>
> > CC: stable@vger.kernel.org # 6.2+
> > Signed-off-by: Filipe Manana <fdmanana@suse.com>
>
> fstests(btrfs/299) will fail with this patch.
Yes, I noticed it later, and it is fixed in v2.
Thanks.
>
> Best Regards
> Wang Yugui (wangyugui@e16-tech.com)
> 2023/05/04
>
> > ---
> > fs/btrfs/backref.c | 15 +++++++--------
> > 1 file changed, 7 insertions(+), 8 deletions(-)
> >
> > diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
> > index e54f0884802a..8e61be3fe9a8 100644
> > --- a/fs/btrfs/backref.c
> > +++ b/fs/btrfs/backref.c
> > @@ -45,7 +45,9 @@ static int check_extent_in_eb(struct btrfs_backref_walk_ctx *ctx,
> > int root_count;
> > bool cached;
> >
> > - if (!btrfs_file_extent_compression(eb, fi) &&
> > + if (!ctx->ignore_extent_item_pos &&
> > + ctx->extent_item_pos > 0 &&
> > + !btrfs_file_extent_compression(eb, fi) &&
> > !btrfs_file_extent_encryption(eb, fi) &&
> > !btrfs_file_extent_other_encoding(eb, fi)) {
> > u64 data_offset;
> > @@ -552,13 +554,10 @@ static int add_all_parents(struct btrfs_backref_walk_ctx *ctx,
> > count++;
> > else
> > goto next;
> > - if (!ctx->ignore_extent_item_pos) {
> > - ret = check_extent_in_eb(ctx, &key, eb, fi, &eie);
> > - if (ret == BTRFS_ITERATE_EXTENT_INODES_STOP ||
> > - ret < 0)
> > - break;
> > - }
> > - if (ret > 0)
> > + ret = check_extent_in_eb(ctx, &key, eb, fi, &eie);
> > + if (ret == BTRFS_ITERATE_EXTENT_INODES_STOP || ret < 0)
> > + break;
> > + else if (ret > 0)
> > goto next;
> > ret = ulist_add_merge_ptr(parents, eb->start,
> > eie, (void **)&old, GFP_NOFS);
> > --
> > 2.35.1
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] btrfs: fix backref walking not returning all inode refs
2023-05-04 10:12 ` [PATCH v2] " fdmanana
@ 2023-05-05 10:03 ` David Sterba
2023-05-08 19:51 ` Filipe Manana
0 siblings, 1 reply; 7+ messages in thread
From: David Sterba @ 2023-05-05 10:03 UTC (permalink / raw)
To: fdmanana; +Cc: linux-btrfs, git, Filipe Manana, stable
On Thu, May 04, 2023 at 11:12:03AM +0100, fdmanana@kernel.org wrote:
> From: Filipe Manana <fdmanana@suse.com>
>
> When using the logical to ino ioctl v2, if the flag to ignore offsets of
> file extent items (BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET) is given, the
> backref walking code ends up not returning references for all file offsets
> of an inode that point to the given logical bytenr. This happens since
> kernel 6.2, commit 6ce6ba534418 ("btrfs: use a single argument for extent
> offset in backref walking functions"), as it mistakenly skipped the search
> for file extent items in a leaf that point to the target extent if that
> flag is given. Instead it should only skip the filtering done by
> check_extent_in_eb() - that is, it should not avoid the calls to that
> function (or find_extent_in_eb(), which uses it).
>
> So fix this by always calling check_extent_in_eb() and find_extent_in_eb()
> and have check_extent_in_eb() do the filtering only if the flag to ignore
> offsets is set.
>
> Fixes: 6ce6ba534418 ("btrfs: use a single argument for extent offset in backref walking functions")
> Reported-by: Vladimir Panteleev <git@vladimir.panteleev.md>
> Link: https://lore.kernel.org/linux-btrfs/CAHhfkvwo=nmzrJSqZ2qMfF-rZB-ab6ahHnCD_sq9h4o8v+M7QQ@mail.gmail.com/
> Tested-by: Vladimir Panteleev <git@vladimir.panteleev.md>
> CC: stable@vger.kernel.org # 6.2+
> Signed-off-by: Filipe Manana <fdmanana@suse.com>
> ---
>
> V2: Remove wrong check for a non-zero extent item offset.
> Apply the same logic at find_parent_nodes(), that is, search for file
> extent items on a leaf if the ignore flag is given - the filtering
> will be done later at check_extent_in_eb(). Spotted by Vladimir Panteleev
> in the thread mentioned above.
Replaced in misc-next, thanks for the quick fix.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] btrfs: fix backref walking not returning all inode refs
2023-05-05 10:03 ` David Sterba
@ 2023-05-08 19:51 ` Filipe Manana
2023-05-09 10:47 ` David Sterba
0 siblings, 1 reply; 7+ messages in thread
From: Filipe Manana @ 2023-05-08 19:51 UTC (permalink / raw)
To: dsterba; +Cc: linux-btrfs, git, Filipe Manana, stable
On Fri, May 5, 2023 at 11:09 AM David Sterba <dsterba@suse.cz> wrote:
>
> On Thu, May 04, 2023 at 11:12:03AM +0100, fdmanana@kernel.org wrote:
> > From: Filipe Manana <fdmanana@suse.com>
> >
> > When using the logical to ino ioctl v2, if the flag to ignore offsets of
> > file extent items (BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET) is given, the
> > backref walking code ends up not returning references for all file offsets
> > of an inode that point to the given logical bytenr. This happens since
> > kernel 6.2, commit 6ce6ba534418 ("btrfs: use a single argument for extent
> > offset in backref walking functions"), as it mistakenly skipped the search
> > for file extent items in a leaf that point to the target extent if that
> > flag is given. Instead it should only skip the filtering done by
> > check_extent_in_eb() - that is, it should not avoid the calls to that
> > function (or find_extent_in_eb(), which uses it).
> >
> > So fix this by always calling check_extent_in_eb() and find_extent_in_eb()
> > and have check_extent_in_eb() do the filtering only if the flag to ignore
> > offsets is set.
> >
> > Fixes: 6ce6ba534418 ("btrfs: use a single argument for extent offset in backref walking functions")
> > Reported-by: Vladimir Panteleev <git@vladimir.panteleev.md>
> > Link: https://lore.kernel.org/linux-btrfs/CAHhfkvwo=nmzrJSqZ2qMfF-rZB-ab6ahHnCD_sq9h4o8v+M7QQ@mail.gmail.com/
> > Tested-by: Vladimir Panteleev <git@vladimir.panteleev.md>
> > CC: stable@vger.kernel.org # 6.2+
> > Signed-off-by: Filipe Manana <fdmanana@suse.com>
> > ---
> >
> > V2: Remove wrong check for a non-zero extent item offset.
> > Apply the same logic at find_parent_nodes(), that is, search for file
> > extent items on a leaf if the ignore flag is given - the filtering
> > will be done later at check_extent_in_eb(). Spotted by Vladimir Panteleev
> > in the thread mentioned above.
>
> Replaced in misc-next, thanks for the quick fix.
Can you please remove it in the meanwhile?
I noticed this isn't quite right and there's still two cases not
working as they should be.
I'll send a v3 after finishing some more tests, probably tomorrow if
everything goes fine.
Thanks.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] btrfs: fix backref walking not returning all inode refs
2023-05-08 19:51 ` Filipe Manana
@ 2023-05-09 10:47 ` David Sterba
0 siblings, 0 replies; 7+ messages in thread
From: David Sterba @ 2023-05-09 10:47 UTC (permalink / raw)
To: Filipe Manana; +Cc: dsterba, linux-btrfs, git, Filipe Manana, stable
On Mon, May 08, 2023 at 08:51:06PM +0100, Filipe Manana wrote:
> On Fri, May 5, 2023 at 11:09 AM David Sterba <dsterba@suse.cz> wrote:
> >
> > On Thu, May 04, 2023 at 11:12:03AM +0100, fdmanana@kernel.org wrote:
> > > From: Filipe Manana <fdmanana@suse.com>
> > >
> > > When using the logical to ino ioctl v2, if the flag to ignore offsets of
> > > file extent items (BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET) is given, the
> > > backref walking code ends up not returning references for all file offsets
> > > of an inode that point to the given logical bytenr. This happens since
> > > kernel 6.2, commit 6ce6ba534418 ("btrfs: use a single argument for extent
> > > offset in backref walking functions"), as it mistakenly skipped the search
> > > for file extent items in a leaf that point to the target extent if that
> > > flag is given. Instead it should only skip the filtering done by
> > > check_extent_in_eb() - that is, it should not avoid the calls to that
> > > function (or find_extent_in_eb(), which uses it).
> > >
> > > So fix this by always calling check_extent_in_eb() and find_extent_in_eb()
> > > and have check_extent_in_eb() do the filtering only if the flag to ignore
> > > offsets is set.
> > >
> > > Fixes: 6ce6ba534418 ("btrfs: use a single argument for extent offset in backref walking functions")
> > > Reported-by: Vladimir Panteleev <git@vladimir.panteleev.md>
> > > Link: https://lore.kernel.org/linux-btrfs/CAHhfkvwo=nmzrJSqZ2qMfF-rZB-ab6ahHnCD_sq9h4o8v+M7QQ@mail.gmail.com/
> > > Tested-by: Vladimir Panteleev <git@vladimir.panteleev.md>
> > > CC: stable@vger.kernel.org # 6.2+
> > > Signed-off-by: Filipe Manana <fdmanana@suse.com>
> > > ---
> > >
> > > V2: Remove wrong check for a non-zero extent item offset.
> > > Apply the same logic at find_parent_nodes(), that is, search for file
> > > extent items on a leaf if the ignore flag is given - the filtering
> > > will be done later at check_extent_in_eb(). Spotted by Vladimir Panteleev
> > > in the thread mentioned above.
> >
> > Replaced in misc-next, thanks for the quick fix.
>
> Can you please remove it in the meanwhile?
> I noticed this isn't quite right and there's still two cases not
> working as they should be.
> I'll send a v3 after finishing some more tests, probably tomorrow if
> everything goes fine.
Ok, removed and pushed.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2023-05-09 10:53 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-05-03 14:27 [PATCH] btrfs: fix backref walking not returning all inode refs fdmanana
2023-05-04 9:41 ` Wang Yugui
2023-05-04 10:13 ` Filipe Manana
2023-05-04 10:12 ` [PATCH v2] " fdmanana
2023-05-05 10:03 ` David Sterba
2023-05-08 19:51 ` Filipe Manana
2023-05-09 10:47 ` David Sterba
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox