aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c102
1 files changed, 68 insertions, 34 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index e9ef644ff56f..c226656f29b7 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -172,7 +172,7 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
172 172
173static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits) 173static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits)
174{ 174{
175 return (cache->flags & bits); 175 return (cache->flags & bits) == bits;
176} 176}
177 177
178static int noinline find_search_start(struct btrfs_root *root, 178static int noinline find_search_start(struct btrfs_root *root,
@@ -1010,6 +1010,35 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
1010 1010
1011} 1011}
1012 1012
1013static int update_space_info(struct btrfs_fs_info *info, u64 flags,
1014 u64 total_bytes, u64 bytes_used,
1015 struct btrfs_space_info **space_info)
1016{
1017 struct btrfs_space_info *found;
1018
1019 found = __find_space_info(info, flags);
1020 if (found) {
1021 found->total_bytes += total_bytes;
1022 found->bytes_used += bytes_used;
1023 WARN_ON(found->total_bytes < found->bytes_used);
1024 *space_info = found;
1025 return 0;
1026 }
1027 found = kmalloc(sizeof(*found), GFP_NOFS);
1028 if (!found)
1029 return -ENOMEM;
1030
1031 list_add(&found->list, &info->space_info);
1032 found->flags = flags;
1033 found->total_bytes = total_bytes;
1034 found->bytes_used = bytes_used;
1035 found->bytes_pinned = 0;
1036 found->full = 0;
1037 *space_info = found;
1038 return 0;
1039}
1040
1041
1013static int do_chunk_alloc(struct btrfs_trans_handle *trans, 1042static int do_chunk_alloc(struct btrfs_trans_handle *trans,
1014 struct btrfs_root *extent_root, u64 alloc_bytes, 1043 struct btrfs_root *extent_root, u64 alloc_bytes,
1015 u64 flags) 1044 u64 flags)
@@ -1021,6 +1050,11 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
1021 int ret; 1050 int ret;
1022 1051
1023 space_info = __find_space_info(extent_root->fs_info, flags); 1052 space_info = __find_space_info(extent_root->fs_info, flags);
1053 if (!space_info) {
1054 ret = update_space_info(extent_root->fs_info, flags,
1055 0, 0, &space_info);
1056 BUG_ON(ret);
1057 }
1024 BUG_ON(!space_info); 1058 BUG_ON(!space_info);
1025 1059
1026 if (space_info->full) 1060 if (space_info->full)
@@ -1044,6 +1078,17 @@ printk("space info full %Lu\n", flags);
1044 extent_root->fs_info->chunk_root->root_key.objectid, 1078 extent_root->fs_info->chunk_root->root_key.objectid,
1045 start, num_bytes); 1079 start, num_bytes);
1046 BUG_ON(ret); 1080 BUG_ON(ret);
1081
1082 if (flags & BTRFS_BLOCK_GROUP_RAID0) {
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 }
1047 return 0; 1092 return 0;
1048} 1093}
1049 1094
@@ -1655,24 +1700,31 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1655 struct btrfs_extent_ref *ref; 1700 struct btrfs_extent_ref *ref;
1656 struct btrfs_path *path; 1701 struct btrfs_path *path;
1657 struct btrfs_key keys[2]; 1702 struct btrfs_key keys[2];
1703 int extra_chunk_alloc_bits = 0;
1658 1704
1659 if (data) { 1705 if (data) {
1660 data = BTRFS_BLOCK_GROUP_DATA; 1706 data = BTRFS_BLOCK_GROUP_DATA | info->extra_data_alloc_bits;
1661 } else if (root == root->fs_info->chunk_root) { 1707 } else if (root == root->fs_info->chunk_root) {
1662 data = BTRFS_BLOCK_GROUP_SYSTEM; 1708 data = BTRFS_BLOCK_GROUP_SYSTEM;
1663 } else { 1709 } else {
1664 data = BTRFS_BLOCK_GROUP_METADATA; 1710 data = BTRFS_BLOCK_GROUP_METADATA | info->extra_alloc_bits;
1665 } 1711 }
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;
1666 1715
1667 if (root->ref_cows) { 1716 if (root->ref_cows) {
1668 if (data != BTRFS_BLOCK_GROUP_METADATA) { 1717 if (!(data & BTRFS_BLOCK_GROUP_METADATA)) {
1669 ret = do_chunk_alloc(trans, root->fs_info->extent_root, 1718 ret = do_chunk_alloc(trans, root->fs_info->extent_root,
1670 2 * 1024 * 1024, 1719 2 * 1024 * 1024,
1671 BTRFS_BLOCK_GROUP_METADATA); 1720 BTRFS_BLOCK_GROUP_METADATA |
1721 info->extra_alloc_bits |
1722 extra_chunk_alloc_bits);
1672 BUG_ON(ret); 1723 BUG_ON(ret);
1673 } 1724 }
1674 ret = do_chunk_alloc(trans, root->fs_info->extent_root, 1725 ret = do_chunk_alloc(trans, root->fs_info->extent_root,
1675 num_bytes + 2 * 1024 * 1024, data); 1726 num_bytes + 2 * 1024 * 1024, data |
1727 extra_chunk_alloc_bits);
1676 BUG_ON(ret); 1728 BUG_ON(ret);
1677 } 1729 }
1678 1730
@@ -2627,34 +2679,6 @@ error:
2627 return ret; 2679 return ret;
2628} 2680}
2629 2681
2630static int update_space_info(struct btrfs_fs_info *info, u64 flags,
2631 u64 total_bytes, u64 bytes_used,
2632 struct btrfs_space_info **space_info)
2633{
2634 struct btrfs_space_info *found;
2635
2636 found = __find_space_info(info, flags);
2637 if (found) {
2638 found->total_bytes += total_bytes;
2639 found->bytes_used += bytes_used;
2640 WARN_ON(found->total_bytes < found->bytes_used);
2641 *space_info = found;
2642 return 0;
2643 }
2644 found = kmalloc(sizeof(*found), GFP_NOFS);
2645 if (!found)
2646 return -ENOMEM;
2647
2648 list_add(&found->list, &info->space_info);
2649 found->flags = flags;
2650 found->total_bytes = total_bytes;
2651 found->bytes_used = bytes_used;
2652 found->bytes_pinned = 0;
2653 found->full = 0;
2654 *space_info = found;
2655 return 0;
2656}
2657
2658int btrfs_read_block_groups(struct btrfs_root *root) 2682int btrfs_read_block_groups(struct btrfs_root *root)
2659{ 2683{
2660 struct btrfs_path *path; 2684 struct btrfs_path *path;
@@ -2712,6 +2736,16 @@ int btrfs_read_block_groups(struct btrfs_root *root)
2712 } else if (cache->flags & BTRFS_BLOCK_GROUP_METADATA) { 2736 } else if (cache->flags & BTRFS_BLOCK_GROUP_METADATA) {
2713 bit = BLOCK_GROUP_METADATA; 2737 bit = BLOCK_GROUP_METADATA;
2714 } 2738 }
2739 if (cache->flags & BTRFS_BLOCK_GROUP_RAID0) {
2740 if (cache->flags & BTRFS_BLOCK_GROUP_DATA) {
2741 info->extra_data_alloc_bits =
2742 BTRFS_BLOCK_GROUP_RAID0;
2743 }
2744 if (cache->flags & BTRFS_BLOCK_GROUP_METADATA) {
2745 info->extra_alloc_bits =
2746 BTRFS_BLOCK_GROUP_RAID0;
2747 }
2748 }
2715 2749
2716 ret = update_space_info(info, cache->flags, found_key.offset, 2750 ret = update_space_info(info, cache->flags, found_key.offset,
2717 btrfs_block_group_used(&cache->item), 2751 btrfs_block_group_used(&cache->item),