summaryrefslogtreecommitdiff
path: root/volumes.h
diff options
context:
space:
mode:
authorQu Wenruo <quwenruo@cn.fujitsu.com>2015-07-23 17:18:08 +0800
committerDavid Sterba <dsterba@suse.com>2015-08-31 19:25:10 +0200
commit595c57d2f4dd3199aacb23b4c68d6aff49f97d29 (patch)
tree5a417bbf5a482dc7fbd30254e4286382b63c655e /volumes.h
parent045dc8fb6cb41bc804af3069f76ac3c94681ea42 (diff)
btrfs-progs: fsck: Check if a metadata tree block crossing stripe boundary
Kernel btrfs_map_block() function has a limitation that it can only map BTRFS_STRIPE_LEN size. That will cause scrub fails to scrub tree block which crosses strip boundary, causing BUG_ON(). Normally, it's OK as metadata is always in metadata chunk and BTRFS_STRIPE_LEN can always be divided by node/leaf size. So without mixed block group, tree block won't cross stripe boundary. But for mixed block group, especially for btrfs converted from ext4, it's almost sure one or more tree blocks are not aligned with node size and cross stripe boundary. Causing bug with kernel scrub. This patch will report the problem, although we don't have a good idea how to fix it in user space until we add the ability to relocate tree block in user space. Also, kernel code should also be checked for such tree block alloc problems. Reported-by: Chris Murphy <lists@colorremedies.com> Reported-by: Zhao Lei <zhaolei@cn.fujitsu.com> Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com> Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'volumes.h')
-rw-r--r--volumes.h10
1 files changed, 10 insertions, 0 deletions
diff --git a/volumes.h b/volumes.h
index 99a3fa11..71d5d663 100644
--- a/volumes.h
+++ b/volumes.h
@@ -148,6 +148,16 @@ struct map_lookup {
#define BTRFS_RAID5_P_STRIPE ((u64)-2)
#define BTRFS_RAID6_Q_STRIPE ((u64)-1)
+/*
+ * Check if the given range cross stripes.
+ * To ensure kernel scrub won't causing bug on with METADATA in mixed
+ * block group
+ */
+static inline int check_crossing_stripes(u64 start, u64 len)
+{
+ return (start / BTRFS_STRIPE_LEN) !=
+ ((start + len) / BTRFS_STRIPE_LEN);
+}
int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
u64 logical, u64 *length, u64 *type,