diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-04-03 16:29:03 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:01 -0400 |
commit | 8790d502e4401a4a3a4175b83a3a47e8d595c771 (patch) | |
tree | 7e01c053d6a99c3c2a6fb71a7338b083e953f0b3 /fs/btrfs/extent-tree.c | |
parent | 0ef8b2428a339e83fe225e82ef8bd0ea3f62b180 (diff) |
Btrfs: Add support for mirroring across drives
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 93 |
1 files changed, 49 insertions, 44 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a34c289aec21..4ab98d8b73fa 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -230,9 +230,13 @@ again: | |||
230 | goto new_group; | 230 | goto new_group; |
231 | if (start + num > total_fs_bytes) | 231 | if (start + num > total_fs_bytes) |
232 | goto new_group; | 232 | goto new_group; |
233 | if (!block_group_bits(cache, data)) { | ||
234 | printk("block group bits don't match %Lu %Lu\n", cache->flags, data); | ||
235 | } | ||
233 | *start_ret = start; | 236 | *start_ret = start; |
234 | return 0; | 237 | return 0; |
235 | } out: | 238 | } |
239 | out: | ||
236 | cache = btrfs_lookup_block_group(root->fs_info, search_start); | 240 | cache = btrfs_lookup_block_group(root->fs_info, search_start); |
237 | if (!cache) { | 241 | if (!cache) { |
238 | printk("Unable to find block group for %Lu\n", search_start); | 242 | printk("Unable to find block group for %Lu\n", search_start); |
@@ -365,14 +369,17 @@ again: | |||
365 | if (cache->key.objectid > total_fs_bytes) | 369 | if (cache->key.objectid > total_fs_bytes) |
366 | break; | 370 | break; |
367 | 371 | ||
368 | if (full_search) | 372 | if (block_group_bits(cache, data)) { |
369 | free_check = cache->key.offset; | 373 | if (full_search) |
370 | else | 374 | free_check = cache->key.offset; |
371 | free_check = div_factor(cache->key.offset, factor); | 375 | else |
376 | free_check = div_factor(cache->key.offset, | ||
377 | factor); | ||
372 | 378 | ||
373 | if (used + cache->pinned < free_check) { | 379 | if (used + cache->pinned < free_check) { |
374 | found_group = cache; | 380 | found_group = cache; |
375 | goto found; | 381 | goto found; |
382 | } | ||
376 | } | 383 | } |
377 | cond_resched(); | 384 | cond_resched(); |
378 | } | 385 | } |
@@ -1038,6 +1045,19 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
1038 | return 0; | 1045 | return 0; |
1039 | } | 1046 | } |
1040 | 1047 | ||
1048 | static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | ||
1049 | { | ||
1050 | u64 extra_flags = flags & (BTRFS_BLOCK_GROUP_RAID0 | | ||
1051 | BTRFS_BLOCK_GROUP_RAID1); | ||
1052 | if (extra_flags) { | ||
1053 | if (flags & BTRFS_BLOCK_GROUP_DATA) | ||
1054 | fs_info->avail_data_alloc_bits |= extra_flags; | ||
1055 | if (flags & BTRFS_BLOCK_GROUP_METADATA) | ||
1056 | fs_info->avail_metadata_alloc_bits |= extra_flags; | ||
1057 | if (flags & BTRFS_BLOCK_GROUP_SYSTEM) | ||
1058 | fs_info->avail_system_alloc_bits |= extra_flags; | ||
1059 | } | ||
1060 | } | ||
1041 | 1061 | ||
1042 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, | 1062 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, |
1043 | struct btrfs_root *extent_root, u64 alloc_bytes, | 1063 | struct btrfs_root *extent_root, u64 alloc_bytes, |
@@ -1060,7 +1080,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
1060 | if (space_info->full) | 1080 | if (space_info->full) |
1061 | return 0; | 1081 | return 0; |
1062 | 1082 | ||
1063 | thresh = div_factor(space_info->total_bytes, 7); | 1083 | thresh = div_factor(space_info->total_bytes, 6); |
1064 | if ((space_info->bytes_used + space_info->bytes_pinned + alloc_bytes) < | 1084 | if ((space_info->bytes_used + space_info->bytes_pinned + alloc_bytes) < |
1065 | thresh) | 1085 | thresh) |
1066 | return 0; | 1086 | return 0; |
@@ -1079,16 +1099,7 @@ printk("space info full %Lu\n", flags); | |||
1079 | start, num_bytes); | 1099 | start, num_bytes); |
1080 | BUG_ON(ret); | 1100 | BUG_ON(ret); |
1081 | 1101 | ||
1082 | if (flags & BTRFS_BLOCK_GROUP_RAID0) { | 1102 | set_avail_alloc_bits(extent_root->fs_info, flags); |
1083 | if (flags & BTRFS_BLOCK_GROUP_DATA) { | ||
1084 | extent_root->fs_info->extra_data_alloc_bits = | ||
1085 | BTRFS_BLOCK_GROUP_RAID0; | ||
1086 | } | ||
1087 | if (flags & BTRFS_BLOCK_GROUP_METADATA) { | ||
1088 | extent_root->fs_info->extra_alloc_bits = | ||
1089 | BTRFS_BLOCK_GROUP_RAID0; | ||
1090 | } | ||
1091 | } | ||
1092 | return 0; | 1103 | return 0; |
1093 | } | 1104 | } |
1094 | 1105 | ||
@@ -1529,6 +1540,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
1529 | 1540 | ||
1530 | if (data & BTRFS_BLOCK_GROUP_METADATA) { | 1541 | if (data & BTRFS_BLOCK_GROUP_METADATA) { |
1531 | last_ptr = &root->fs_info->last_alloc; | 1542 | last_ptr = &root->fs_info->last_alloc; |
1543 | empty_cluster = 256 * 1024; | ||
1532 | } | 1544 | } |
1533 | 1545 | ||
1534 | if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD)) { | 1546 | if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD)) { |
@@ -1693,6 +1705,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1693 | u64 root_used; | 1705 | u64 root_used; |
1694 | u64 search_start = 0; | 1706 | u64 search_start = 0; |
1695 | u64 new_hint; | 1707 | u64 new_hint; |
1708 | u64 alloc_profile; | ||
1696 | u32 sizes[2]; | 1709 | u32 sizes[2]; |
1697 | struct btrfs_fs_info *info = root->fs_info; | 1710 | struct btrfs_fs_info *info = root->fs_info; |
1698 | struct btrfs_root *extent_root = info->extent_root; | 1711 | struct btrfs_root *extent_root = info->extent_root; |
@@ -1700,31 +1713,32 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1700 | struct btrfs_extent_ref *ref; | 1713 | struct btrfs_extent_ref *ref; |
1701 | struct btrfs_path *path; | 1714 | struct btrfs_path *path; |
1702 | struct btrfs_key keys[2]; | 1715 | struct btrfs_key keys[2]; |
1703 | int extra_chunk_alloc_bits = 0; | ||
1704 | 1716 | ||
1705 | if (data) { | 1717 | if (data) { |
1706 | data = BTRFS_BLOCK_GROUP_DATA | info->extra_data_alloc_bits; | 1718 | alloc_profile = info->avail_data_alloc_bits & |
1719 | info->data_alloc_profile; | ||
1720 | data = BTRFS_BLOCK_GROUP_DATA | alloc_profile; | ||
1707 | } else if (root == root->fs_info->chunk_root) { | 1721 | } else if (root == root->fs_info->chunk_root) { |
1708 | data = BTRFS_BLOCK_GROUP_SYSTEM; | 1722 | alloc_profile = info->avail_system_alloc_bits & |
1723 | info->system_alloc_profile; | ||
1724 | data = BTRFS_BLOCK_GROUP_SYSTEM | alloc_profile; | ||
1709 | } else { | 1725 | } else { |
1710 | data = BTRFS_BLOCK_GROUP_METADATA | info->extra_alloc_bits; | 1726 | alloc_profile = info->avail_metadata_alloc_bits & |
1727 | info->metadata_alloc_profile; | ||
1728 | data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile; | ||
1711 | } | 1729 | } |
1712 | if (btrfs_super_num_devices(&info->super_copy) > 1 && | ||
1713 | !(data & BTRFS_BLOCK_GROUP_SYSTEM)) | ||
1714 | extra_chunk_alloc_bits = BTRFS_BLOCK_GROUP_RAID0; | ||
1715 | 1730 | ||
1716 | if (root->ref_cows) { | 1731 | if (root->ref_cows) { |
1717 | if (!(data & BTRFS_BLOCK_GROUP_METADATA)) { | 1732 | if (!(data & BTRFS_BLOCK_GROUP_METADATA)) { |
1718 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, | 1733 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, |
1719 | 2 * 1024 * 1024, | 1734 | 2 * 1024 * 1024, |
1720 | BTRFS_BLOCK_GROUP_METADATA | | 1735 | BTRFS_BLOCK_GROUP_METADATA | |
1721 | info->extra_alloc_bits | | 1736 | (info->metadata_alloc_profile & |
1722 | extra_chunk_alloc_bits); | 1737 | info->avail_metadata_alloc_bits)); |
1723 | BUG_ON(ret); | 1738 | BUG_ON(ret); |
1724 | } | 1739 | } |
1725 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, | 1740 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, |
1726 | num_bytes + 2 * 1024 * 1024, data | | 1741 | num_bytes + 2 * 1024 * 1024, data); |
1727 | extra_chunk_alloc_bits); | ||
1728 | BUG_ON(ret); | 1742 | BUG_ON(ret); |
1729 | } | 1743 | } |
1730 | 1744 | ||
@@ -2046,12 +2060,12 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans, | |||
2046 | if (!next || !btrfs_buffer_uptodate(next)) { | 2060 | if (!next || !btrfs_buffer_uptodate(next)) { |
2047 | free_extent_buffer(next); | 2061 | free_extent_buffer(next); |
2048 | reada_walk_down(root, cur, path->slots[*level]); | 2062 | reada_walk_down(root, cur, path->slots[*level]); |
2063 | |||
2064 | mutex_unlock(&root->fs_info->fs_mutex); | ||
2049 | next = read_tree_block(root, bytenr, blocksize); | 2065 | next = read_tree_block(root, bytenr, blocksize); |
2066 | mutex_lock(&root->fs_info->fs_mutex); | ||
2050 | 2067 | ||
2051 | /* we used to drop the lock above, keep the | 2068 | /* we've dropped the lock, double check */ |
2052 | * code to double check so that we won't forget | ||
2053 | * when we drop the lock again in the future | ||
2054 | */ | ||
2055 | ret = lookup_extent_ref(trans, root, bytenr, | 2069 | ret = lookup_extent_ref(trans, root, bytenr, |
2056 | blocksize, &refs); | 2070 | blocksize, &refs); |
2057 | BUG_ON(ret); | 2071 | BUG_ON(ret); |
@@ -2739,16 +2753,7 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
2739 | } else if (cache->flags & BTRFS_BLOCK_GROUP_METADATA) { | 2753 | } else if (cache->flags & BTRFS_BLOCK_GROUP_METADATA) { |
2740 | bit = BLOCK_GROUP_METADATA; | 2754 | bit = BLOCK_GROUP_METADATA; |
2741 | } | 2755 | } |
2742 | if (cache->flags & BTRFS_BLOCK_GROUP_RAID0) { | 2756 | set_avail_alloc_bits(info, cache->flags); |
2743 | if (cache->flags & BTRFS_BLOCK_GROUP_DATA) { | ||
2744 | info->extra_data_alloc_bits = | ||
2745 | BTRFS_BLOCK_GROUP_RAID0; | ||
2746 | } | ||
2747 | if (cache->flags & BTRFS_BLOCK_GROUP_METADATA) { | ||
2748 | info->extra_alloc_bits = | ||
2749 | BTRFS_BLOCK_GROUP_RAID0; | ||
2750 | } | ||
2751 | } | ||
2752 | 2757 | ||
2753 | ret = update_space_info(info, cache->flags, found_key.offset, | 2758 | ret = update_space_info(info, cache->flags, found_key.offset, |
2754 | btrfs_block_group_used(&cache->item), | 2759 | btrfs_block_group_used(&cache->item), |