summaryrefslogtreecommitdiff
path: root/volumes.c
diff options
context:
space:
mode:
authorQu Wenruo <quwenruo@cn.fujitsu.com>2017-05-31 13:56:08 +0800
committerDavid Sterba <dsterba@suse.com>2017-07-03 13:35:11 +0200
commit6e7b1bbdecfa89d4bd3b51e56d01b29274fe3902 (patch)
tree693e9bdce25ac9e9fd9930bb91cd5f7ef3a8c0db /volumes.c
parentd07f45bc25872acd9e88de9f6e3b2feeb8ad0423 (diff)
btrfs-progs: Introduce function to get correct stripe length
Introduce a new function, btrfs_get_chunk_stripe_len() to get correct stripe length. This is very handy for lowmem mode, which checks the mapping between device extent and chunk item. Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'volumes.c')
-rw-r--r--volumes.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/volumes.c b/volumes.c
index fdc3a94..990300f 100644
--- a/volumes.c
+++ b/volumes.c
@@ -2287,3 +2287,47 @@ out:
return ret;
}
+
+/*
+ * Get stripe length from chunk item and its stripe items
+ *
+ * Caller should only call this function after validating the chunk item
+ * by using btrfs_check_chunk_valid().
+ */
+u64 btrfs_stripe_length(struct btrfs_fs_info *fs_info,
+ struct extent_buffer *leaf,
+ struct btrfs_chunk *chunk)
+{
+ u64 stripe_len;
+ u64 chunk_len;
+ u32 num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
+ u64 profile = btrfs_chunk_type(leaf, chunk) &
+ BTRFS_BLOCK_GROUP_PROFILE_MASK;
+
+ chunk_len = btrfs_chunk_length(leaf, chunk);
+
+ switch (profile) {
+ case 0: /* Single profile */
+ case BTRFS_BLOCK_GROUP_RAID1:
+ case BTRFS_BLOCK_GROUP_DUP:
+ stripe_len = chunk_len;
+ break;
+ case BTRFS_BLOCK_GROUP_RAID0:
+ stripe_len = chunk_len / num_stripes;
+ break;
+ case BTRFS_BLOCK_GROUP_RAID5:
+ stripe_len = chunk_len / (num_stripes - 1);
+ break;
+ case BTRFS_BLOCK_GROUP_RAID6:
+ stripe_len = chunk_len / (num_stripes - 2);
+ break;
+ case BTRFS_BLOCK_GROUP_RAID10:
+ stripe_len = chunk_len / (num_stripes /
+ btrfs_chunk_sub_stripes(leaf, chunk));
+ break;
+ default:
+ /* Invalid chunk profile found */
+ BUG_ON(1);
+ }
+ return stripe_len;
+}