diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-11-06 10:26:29 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:57 -0400 |
commit | f84a8b362d9785ca1fa0598d8a90f35184bd8750 (patch) | |
tree | 5161beaf9981b793a3efb1034bef8715bc456572 | |
parent | a273208edd55463b3bcd8b77a6fe8ba54afc6940 (diff) |
Btrfs: Optimize allocations as we need to mix data and metadata into one group
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 42 | ||||
-rw-r--r-- | fs/btrfs/tree-defrag.c | 6 |
3 files changed, 43 insertions, 7 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index d82afb618bf1..f7907b02fa77 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -279,6 +279,8 @@ struct btrfs_csum_item { | |||
279 | 279 | ||
280 | 280 | ||
281 | #define BTRFS_BLOCK_GROUP_DATA 1 | 281 | #define BTRFS_BLOCK_GROUP_DATA 1 |
282 | #define BTRFS_BLOCK_GROUP_MIXED 2 | ||
283 | |||
282 | struct btrfs_block_group_item { | 284 | struct btrfs_block_group_item { |
283 | __le64 used; | 285 | __le64 used; |
284 | u8 flags; | 286 | u8 flags; |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 9eb2ee02f643..d54ab8ef06d5 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -168,11 +168,13 @@ static u64 find_search_start(struct btrfs_root *root, | |||
168 | u64 last; | 168 | u64 last; |
169 | u64 start = 0; | 169 | u64 start = 0; |
170 | u64 end = 0; | 170 | u64 end = 0; |
171 | int wrapped = 0; | ||
171 | 172 | ||
172 | again: | 173 | again: |
173 | ret = cache_block_group(root, cache); | 174 | ret = cache_block_group(root, cache); |
174 | if (ret) | 175 | if (ret) |
175 | goto out; | 176 | goto out; |
177 | |||
176 | last = max(search_start, cache->key.objectid); | 178 | last = max(search_start, cache->key.objectid); |
177 | 179 | ||
178 | while(1) { | 180 | while(1) { |
@@ -195,8 +197,15 @@ out: | |||
195 | 197 | ||
196 | new_group: | 198 | new_group: |
197 | last = cache->key.objectid + cache->key.offset; | 199 | last = cache->key.objectid + cache->key.offset; |
200 | wrapped: | ||
198 | cache = btrfs_lookup_block_group(root->fs_info, last); | 201 | cache = btrfs_lookup_block_group(root->fs_info, last); |
199 | if (!cache) { | 202 | if (!cache) { |
203 | if (!wrapped) { | ||
204 | wrapped = 1; | ||
205 | last = search_start; | ||
206 | data = BTRFS_BLOCK_GROUP_MIXED; | ||
207 | goto wrapped; | ||
208 | } | ||
200 | return search_start; | 209 | return search_start; |
201 | } | 210 | } |
202 | cache = btrfs_find_block_group(root, cache, last, data, 0); | 211 | cache = btrfs_find_block_group(root, cache, last, data, 0); |
@@ -236,9 +245,11 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
236 | block_group_cache = &info->block_group_cache; | 245 | block_group_cache = &info->block_group_cache; |
237 | 246 | ||
238 | if (!owner) | 247 | if (!owner) |
239 | factor = 5; | 248 | factor = 8; |
240 | 249 | ||
241 | if (data) | 250 | if (data == BTRFS_BLOCK_GROUP_MIXED) |
251 | bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA; | ||
252 | else if (data) | ||
242 | bit = BLOCK_GROUP_DATA; | 253 | bit = BLOCK_GROUP_DATA; |
243 | else | 254 | else |
244 | bit = BLOCK_GROUP_METADATA; | 255 | bit = BLOCK_GROUP_METADATA; |
@@ -246,14 +257,16 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
246 | if (search_start) { | 257 | if (search_start) { |
247 | struct btrfs_block_group_cache *shint; | 258 | struct btrfs_block_group_cache *shint; |
248 | shint = btrfs_lookup_block_group(info, search_start); | 259 | shint = btrfs_lookup_block_group(info, search_start); |
249 | if (shint && shint->data == data) { | 260 | if (shint && (shint->data == data || |
261 | shint->data == BTRFS_BLOCK_GROUP_MIXED)) { | ||
250 | used = btrfs_block_group_used(&shint->item); | 262 | used = btrfs_block_group_used(&shint->item); |
251 | if (used < div_factor(shint->key.offset, factor)) { | 263 | if (used < div_factor(shint->key.offset, factor)) { |
252 | return shint; | 264 | return shint; |
253 | } | 265 | } |
254 | } | 266 | } |
255 | } | 267 | } |
256 | if (hint && hint->data == data) { | 268 | if (hint && (hint->data == data || |
269 | hint->data == BTRFS_BLOCK_GROUP_MIXED)) { | ||
257 | used = btrfs_block_group_used(&hint->item); | 270 | used = btrfs_block_group_used(&hint->item); |
258 | if (used < div_factor(hint->key.offset, factor)) { | 271 | if (used < div_factor(hint->key.offset, factor)) { |
259 | return hint; | 272 | return hint; |
@@ -592,12 +605,16 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
592 | if (data) { | 605 | if (data) { |
593 | bit_to_clear = BLOCK_GROUP_METADATA; | 606 | bit_to_clear = BLOCK_GROUP_METADATA; |
594 | bit_to_set = BLOCK_GROUP_DATA; | 607 | bit_to_set = BLOCK_GROUP_DATA; |
608 | cache->item.flags &= | ||
609 | ~BTRFS_BLOCK_GROUP_MIXED; | ||
595 | cache->item.flags |= | 610 | cache->item.flags |= |
596 | BTRFS_BLOCK_GROUP_DATA; | 611 | BTRFS_BLOCK_GROUP_DATA; |
597 | } else { | 612 | } else { |
598 | bit_to_clear = BLOCK_GROUP_DATA; | 613 | bit_to_clear = BLOCK_GROUP_DATA; |
599 | bit_to_set = BLOCK_GROUP_METADATA; | 614 | bit_to_set = BLOCK_GROUP_METADATA; |
600 | cache->item.flags &= | 615 | cache->item.flags &= |
616 | ~BTRFS_BLOCK_GROUP_MIXED; | ||
617 | cache->item.flags &= | ||
601 | ~BTRFS_BLOCK_GROUP_DATA; | 618 | ~BTRFS_BLOCK_GROUP_DATA; |
602 | } | 619 | } |
603 | clear_extent_bits(&info->block_group_cache, | 620 | clear_extent_bits(&info->block_group_cache, |
@@ -606,6 +623,14 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
606 | set_extent_bits(&info->block_group_cache, | 623 | set_extent_bits(&info->block_group_cache, |
607 | start, end, bit_to_set, | 624 | start, end, bit_to_set, |
608 | GFP_NOFS); | 625 | GFP_NOFS); |
626 | } else if (cache->data != data && | ||
627 | cache->data != BTRFS_BLOCK_GROUP_MIXED) { | ||
628 | cache->data = BTRFS_BLOCK_GROUP_MIXED; | ||
629 | set_extent_bits(&info->block_group_cache, | ||
630 | start, end, | ||
631 | BLOCK_GROUP_DATA | | ||
632 | BLOCK_GROUP_METADATA, | ||
633 | GFP_NOFS); | ||
609 | } | 634 | } |
610 | old_val += num_bytes; | 635 | old_val += num_bytes; |
611 | } else { | 636 | } else { |
@@ -886,6 +911,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
886 | struct btrfs_block_group_cache *block_group; | 911 | struct btrfs_block_group_cache *block_group; |
887 | int full_scan = 0; | 912 | int full_scan = 0; |
888 | int wrapped = 0; | 913 | int wrapped = 0; |
914 | u64 cached_start; | ||
889 | 915 | ||
890 | WARN_ON(num_bytes < root->sectorsize); | 916 | WARN_ON(num_bytes < root->sectorsize); |
891 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); | 917 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); |
@@ -910,6 +936,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
910 | check_failed: | 936 | check_failed: |
911 | search_start = find_search_start(root, &block_group, | 937 | search_start = find_search_start(root, &block_group, |
912 | search_start, total_needed, data); | 938 | search_start, total_needed, data); |
939 | cached_start = search_start; | ||
913 | btrfs_init_path(path); | 940 | btrfs_init_path(path); |
914 | ins->objectid = search_start; | 941 | ins->objectid = search_start; |
915 | ins->offset = 0; | 942 | ins->offset = 0; |
@@ -1532,9 +1559,12 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
1532 | key.objectid = found_key.objectid + found_key.offset; | 1559 | key.objectid = found_key.objectid + found_key.offset; |
1533 | btrfs_release_path(root, path); | 1560 | btrfs_release_path(root, path); |
1534 | 1561 | ||
1535 | if (cache->item.flags & BTRFS_BLOCK_GROUP_DATA) { | 1562 | if (cache->item.flags & BTRFS_BLOCK_GROUP_MIXED) { |
1563 | bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA; | ||
1564 | cache->data = BTRFS_BLOCK_GROUP_MIXED; | ||
1565 | } else if (cache->item.flags & BTRFS_BLOCK_GROUP_DATA) { | ||
1536 | bit = BLOCK_GROUP_DATA; | 1566 | bit = BLOCK_GROUP_DATA; |
1537 | cache->data = 1; | 1567 | cache->data = BTRFS_BLOCK_GROUP_DATA; |
1538 | } else { | 1568 | } else { |
1539 | bit = BLOCK_GROUP_METADATA; | 1569 | bit = BLOCK_GROUP_METADATA; |
1540 | cache->data = 0; | 1570 | cache->data = 0; |
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c index 6ef1ba5f9c2f..3994795edfeb 100644 --- a/fs/btrfs/tree-defrag.c +++ b/fs/btrfs/tree-defrag.c | |||
@@ -58,6 +58,10 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans, | |||
58 | if (root->fs_info->extent_root == root) | 58 | if (root->fs_info->extent_root == root) |
59 | is_extent = 1; | 59 | is_extent = 1; |
60 | 60 | ||
61 | if (*level == 1 && cache_only && path->nodes[1] && | ||
62 | !btrfs_buffer_defrag(path->nodes[1])) { | ||
63 | goto out; | ||
64 | } | ||
61 | while(*level > 0) { | 65 | while(*level > 0) { |
62 | WARN_ON(*level < 0); | 66 | WARN_ON(*level < 0); |
63 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | 67 | WARN_ON(*level >= BTRFS_MAX_LEVEL); |
@@ -116,7 +120,7 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans, | |||
116 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | 120 | WARN_ON(*level >= BTRFS_MAX_LEVEL); |
117 | 121 | ||
118 | btrfs_clear_buffer_defrag(path->nodes[*level]); | 122 | btrfs_clear_buffer_defrag(path->nodes[*level]); |
119 | 123 | out: | |
120 | free_extent_buffer(path->nodes[*level]); | 124 | free_extent_buffer(path->nodes[*level]); |
121 | path->nodes[*level] = NULL; | 125 | path->nodes[*level] = NULL; |
122 | *level += 1; | 126 | *level += 1; |