aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-11-06 10:26:29 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:57 -0400
commitf84a8b362d9785ca1fa0598d8a90f35184bd8750 (patch)
tree5161beaf9981b793a3efb1034bef8715bc456572 /fs
parenta273208edd55463b3bcd8b77a6fe8ba54afc6940 (diff)
Btrfs: Optimize allocations as we need to mix data and metadata into one group
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/extent-tree.c42
-rw-r--r--fs/btrfs/tree-defrag.c6
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
282struct btrfs_block_group_item { 284struct 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
172again: 173again:
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
196new_group: 198new_group:
197 last = cache->key.objectid + cache->key.offset; 199 last = cache->key.objectid + cache->key.offset;
200wrapped:
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
910check_failed: 936check_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 123out:
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;