aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2022-10-03 15:57:30 +0100
committerDavid Sterba <dsterba@suse.com>2022-10-07 17:55:00 +0200
commit96dbcc0072acf4f9565a16e8da96e57e5cee1068 (patch)
tree9be0247eea88deca6d49badd2379f8de403a08fb
parentbtrfs: set generation before calling btrfs_clean_tree_block in btrfs_init_new_buffer (diff)
downloadlinux-dev-96dbcc0072acf4f9565a16e8da96e57e5cee1068.tar.xz
linux-dev-96dbcc0072acf4f9565a16e8da96e57e5cee1068.zip
btrfs: add missing path cache update during fiemap
When looking the stored result for a cached path node, if the stored result is valid and has a value of true, we must update all the nodes for all levels below it with a result of true as well. This is necessary when moving from one leaf in the fs tree to the next one, as well as when moving from a node at any level to the next node at the same level. Currently this logic is missing as it was somehow forgotten by a recent patch with the subject: "btrfs: speedup checking for extent sharedness during fiemap". This adds the missing logic, which is the counter part to what we do when adding a shared node to the cache at store_backref_shared_cache(). Fixes: 12a824dc67a6 ("btrfs: speedup checking for extent sharedness during fiemap") Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/backref.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index dce3a16996b9..3c0c1f626c75 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1557,6 +1557,19 @@ static bool lookup_backref_shared_cache(struct btrfs_backref_shared_cache *cache
return false;
*is_shared = entry->is_shared;
+ /*
+ * If the node at this level is shared, than all nodes below are also
+ * shared. Currently some of the nodes below may be marked as not shared
+ * because we have just switched from one leaf to another, and switched
+ * also other nodes above the leaf and below the current level, so mark
+ * them as shared.
+ */
+ if (*is_shared) {
+ for (int i = 0; i < level; i++) {
+ cache->entries[i].is_shared = true;
+ cache->entries[i].gen = entry->gen;
+ }
+ }
return true;
}