summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorethanwu <ethanwu@synology.com>2020-02-07 17:38:17 +0800
committerDavid Sterba <dsterba@suse.com>2020-03-23 17:01:40 +0100
commitcfc0eed0ec89db7c4a8d461174cabfaa4a0912c7 (patch)
tree5f0b20b8464113a5508a6f35baa2e5503a4cf5b2
parented58f2e66e849c34826083e5a6c1b506ee8a4d8e (diff)
btrfs: backref, only search backref entries from leaves of the same root
We could have some nodes/leaves in subvolume whose owner are not the that subvolume. In this way, when we resolve normal backrefs of that subvolume, we should avoid collecting those references from these blocks. Reviewed-by: Josef Bacik <josef@toxicpanda.com> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: ethanwu <ethanwu@synology.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/backref.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 04e9d2efa958..19a3ae79a0a8 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -443,11 +443,14 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
* slot == nritems.
* 2. We are searching for normal backref but bytenr of this leaf
* matches shared data backref
+ * 3. The leaf owner is not equal to the root we are searching
+ *
* For these cases, go to the next leaf before we continue.
*/
eb = path->nodes[0];
if (path->slots[0] >= btrfs_header_nritems(eb) ||
- is_shared_data_backref(preftrees, eb->start)) {
+ is_shared_data_backref(preftrees, eb->start) ||
+ ref->root_id != btrfs_header_owner(eb)) {
if (time_seq == SEQ_LAST)
ret = btrfs_next_leaf(root, path);
else
@@ -466,9 +469,12 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
/*
* We are searching for normal backref but bytenr of this leaf
- * matches shared data backref.
+ * matches shared data backref, OR
+ * the leaf owner is not equal to the root we are searching for
*/
- if (slot == 0 && is_shared_data_backref(preftrees, eb->start)) {
+ if (slot == 0 &&
+ (is_shared_data_backref(preftrees, eb->start) ||
+ ref->root_id != btrfs_header_owner(eb))) {
if (time_seq == SEQ_LAST)
ret = btrfs_next_leaf(root, path);
else