aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h5
-rw-r--r--fs/btrfs/extent-tree.c85
2 files changed, 65 insertions, 25 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 756ea9d0123b..1bb62867deda 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -249,10 +249,13 @@ struct btrfs_device_item {
249/* tag for the radix tree of block groups in ram */ 249/* tag for the radix tree of block groups in ram */
250#define BTRFS_BLOCK_GROUP_DIRTY 0 250#define BTRFS_BLOCK_GROUP_DIRTY 0
251#define BTRFS_BLOCK_GROUP_AVAIL 1 251#define BTRFS_BLOCK_GROUP_AVAIL 1
252#define BTRFS_BLOCK_GROUP_HINTS 8
253#define BTRFS_BLOCK_GROUP_SIZE (256 * 1024 * 1024) 252#define BTRFS_BLOCK_GROUP_SIZE (256 * 1024 * 1024)
253
254
255#define BTRFS_BLOCK_GROUP_DATA 1
254struct btrfs_block_group_item { 256struct btrfs_block_group_item {
255 __le64 used; 257 __le64 used;
258 u8 flags;
256} __attribute__ ((__packed__)); 259} __attribute__ ((__packed__));
257 260
258struct btrfs_block_group_cache { 261struct btrfs_block_group_cache {
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index a366415e03a6..b6dc020bdde9 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -232,6 +232,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
232 struct btrfs_block_group_cache *found_group = NULL; 232 struct btrfs_block_group_cache *found_group = NULL;
233 struct btrfs_fs_info *info = root->fs_info; 233 struct btrfs_fs_info *info = root->fs_info;
234 struct radix_tree_root *radix; 234 struct radix_tree_root *radix;
235 struct radix_tree_root *swap_radix;
235 u64 used; 236 u64 used;
236 u64 last = 0; 237 u64 last = 0;
237 u64 hint_last; 238 u64 hint_last;
@@ -239,14 +240,18 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
239 int ret; 240 int ret;
240 int full_search = 0; 241 int full_search = 0;
241 int factor = 8; 242 int factor = 8;
243 int data_swap = 0;
242 244
243 if (!owner) 245 if (!owner)
244 factor = 5; 246 factor = 5;
245 247
246 if (data) 248 if (data) {
247 radix = &info->block_group_data_radix; 249 radix = &info->block_group_data_radix;
248 else 250 swap_radix = &info->block_group_radix;
251 } else {
249 radix = &info->block_group_radix; 252 radix = &info->block_group_radix;
253 swap_radix = &info->block_group_data_radix;
254 }
250 255
251 if (search_start) { 256 if (search_start) {
252 struct btrfs_block_group_cache *shint; 257 struct btrfs_block_group_cache *shint;
@@ -334,15 +339,27 @@ again:
334 cond_resched(); 339 cond_resched();
335 } 340 }
336 if (!full_search) { 341 if (!full_search) {
337printk("find block group doing full search data %d start %Lu\n", data, search_start);
338 last = search_start; 342 last = search_start;
339 full_search = 1; 343 full_search = 1;
340 goto again; 344 goto again;
341 } 345 }
346 if (!data_swap) {
347 struct radix_tree_root *tmp = radix;
348 data_swap = 1;
349 radix = swap_radix;
350 swap_radix = tmp;
351 last = search_start;
352 goto again;
353 }
342 if (!found_group) { 354 if (!found_group) {
343printk("find block group bailing to zero data %d\n", data); 355printk("find block group bailing to zero data %d\n", data);
344 ret = radix_tree_gang_lookup(radix, 356 ret = radix_tree_gang_lookup(radix,
345 (void **)&found_group, 0, 1); 357 (void **)&found_group, 0, 1);
358 if (ret == 0) {
359 ret = radix_tree_gang_lookup(swap_radix,
360 (void **)&found_group,
361 0, 1);
362 }
346 BUG_ON(ret != 1); 363 BUG_ON(ret != 1);
347 } 364 }
348found: 365found:
@@ -552,7 +569,8 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
552 569
553static int update_block_group(struct btrfs_trans_handle *trans, 570static int update_block_group(struct btrfs_trans_handle *trans,
554 struct btrfs_root *root, 571 struct btrfs_root *root,
555 u64 blocknr, u64 num, int alloc, int mark_free) 572 u64 blocknr, u64 num, int alloc, int mark_free,
573 int data)
556{ 574{
557 struct btrfs_block_group_cache *cache; 575 struct btrfs_block_group_cache *cache;
558 struct btrfs_fs_info *info = root->fs_info; 576 struct btrfs_fs_info *info = root->fs_info;
@@ -560,6 +578,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
560 u64 old_val; 578 u64 old_val;
561 u64 block_in_group; 579 u64 block_in_group;
562 u64 i; 580 u64 i;
581 int ret;
563 582
564 while(total) { 583 while(total) {
565 cache = lookup_block_group(info, blocknr); 584 cache = lookup_block_group(info, blocknr);
@@ -577,7 +596,6 @@ static int update_block_group(struct btrfs_trans_handle *trans,
577 old_val = btrfs_block_group_used(&cache->item); 596 old_val = btrfs_block_group_used(&cache->item);
578 num = min(total, cache->key.offset - block_in_group); 597 num = min(total, cache->key.offset - block_in_group);
579 if (alloc) { 598 if (alloc) {
580 old_val += num;
581 if (blocknr > cache->last_alloc) 599 if (blocknr > cache->last_alloc)
582 cache->last_alloc = blocknr; 600 cache->last_alloc = blocknr;
583 if (!cache->data) { 601 if (!cache->data) {
@@ -586,6 +604,30 @@ static int update_block_group(struct btrfs_trans_handle *trans,
586 blocknr + i); 604 blocknr + i);
587 } 605 }
588 } 606 }
607 if (cache->data != data &&
608 old_val < cache->key.offset / 2) {
609printk("changing block group %Lu from %d to %d\n", cache->key.objectid, cache->data, data);
610 cache->data = data;
611 radix_tree_delete(cache->radix,
612 cache->key.objectid +
613 cache->key.offset - 1);
614
615 if (data) {
616 cache->radix =
617 &info->block_group_data_radix;
618 cache->item.flags |=
619 BTRFS_BLOCK_GROUP_DATA;
620 } else {
621 cache->radix = &info->block_group_radix;
622 cache->item.flags &=
623 ~BTRFS_BLOCK_GROUP_DATA;
624 }
625 ret = radix_tree_insert(cache->radix,
626 cache->key.objectid +
627 cache->key.offset - 1,
628 (void *)cache);
629 }
630 old_val += num;
589 } else { 631 } else {
590 old_val -= num; 632 old_val -= num;
591 if (blocknr < cache->first_free) 633 if (blocknr < cache->first_free)
@@ -596,8 +638,8 @@ static int update_block_group(struct btrfs_trans_handle *trans,
596 blocknr + i); 638 blocknr + i);
597 } 639 }
598 } 640 }
599 if (old_val < (cache->key.offset * 5) / 10 && 641 if (old_val < cache->key.offset / 2 &&
600 old_val + num >= (cache->key.offset * 5) / 10) { 642 old_val + num >= cache->key.offset / 2) {
601printk("group %Lu now available\n", cache->key.objectid); 643printk("group %Lu now available\n", cache->key.objectid);
602 radix_tree_tag_set(cache->radix, 644 radix_tree_tag_set(cache->radix,
603 cache->key.objectid + 645 cache->key.objectid +
@@ -779,7 +821,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
779 if (ret) 821 if (ret)
780 BUG(); 822 BUG();
781 ret = update_block_group(trans, root, blocknr, num_blocks, 0, 823 ret = update_block_group(trans, root, blocknr, num_blocks, 0,
782 mark_free); 824 mark_free, 0);
783 BUG_ON(ret); 825 BUG_ON(ret);
784 } 826 }
785 btrfs_free_path(path); 827 btrfs_free_path(path);
@@ -909,10 +951,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
909 } 951 }
910 952
911check_failed: 953check_failed:
912 if (!full_scan && block_group->data != data) 954 if (!block_group->data)
913 WARN_ON(1);
914
915 if (!data)
916 search_start = find_search_start(root, &block_group, 955 search_start = find_search_start(root, &block_group,
917 search_start, total_needed); 956 search_start, total_needed);
918 else 957 else
@@ -1142,7 +1181,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1142 info->extent_tree_insert[info->extent_tree_insert_nr++] = 1181 info->extent_tree_insert[info->extent_tree_insert_nr++] =
1143 ins->objectid; 1182 ins->objectid;
1144 ret = update_block_group(trans, root, 1183 ret = update_block_group(trans, root,
1145 ins->objectid, ins->offset, 1, 0); 1184 ins->objectid, ins->offset, 1, 0, 0);
1146 BUG_ON(ret); 1185 BUG_ON(ret);
1147 return 0; 1186 return 0;
1148 } 1187 }
@@ -1208,7 +1247,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1208 if (pending_ret) { 1247 if (pending_ret) {
1209 return pending_ret; 1248 return pending_ret;
1210 } 1249 }
1211 ret = update_block_group(trans, root, ins->objectid, ins->offset, 1, 0); 1250 ret = update_block_group(trans, root, ins->objectid, ins->offset, 1, 0,
1251 data);
1212 return 0; 1252 return 0;
1213} 1253}
1214 1254
@@ -1477,7 +1517,6 @@ int btrfs_read_block_groups(struct btrfs_root *root)
1477 struct btrfs_leaf *leaf; 1517 struct btrfs_leaf *leaf;
1478 u64 group_size_blocks = BTRFS_BLOCK_GROUP_SIZE / root->blocksize; 1518 u64 group_size_blocks = BTRFS_BLOCK_GROUP_SIZE / root->blocksize;
1479 u64 used; 1519 u64 used;
1480 u64 nr = 0;
1481 1520
1482 root = info->extent_root; 1521 root = info->extent_root;
1483 key.objectid = 0; 1522 key.objectid = 0;
@@ -1505,13 +1544,16 @@ int btrfs_read_block_groups(struct btrfs_root *root)
1505 break; 1544 break;
1506 } 1545 }
1507 1546
1508 if (nr % 3) 1547 bi = btrfs_item_ptr(leaf, path->slots[0],
1548 struct btrfs_block_group_item);
1549 if (bi->flags & BTRFS_BLOCK_GROUP_DATA) {
1509 radix = &info->block_group_data_radix; 1550 radix = &info->block_group_data_radix;
1510 else 1551 cache->data = 1;
1552 } else {
1511 radix = &info->block_group_radix; 1553 radix = &info->block_group_radix;
1554 cache->data = 0;
1555 }
1512 1556
1513 bi = btrfs_item_ptr(leaf, path->slots[0],
1514 struct btrfs_block_group_item);
1515 memcpy(&cache->item, bi, sizeof(*bi)); 1557 memcpy(&cache->item, bi, sizeof(*bi));
1516 memcpy(&cache->key, &found_key, sizeof(found_key)); 1558 memcpy(&cache->key, &found_key, sizeof(found_key));
1517 cache->last_alloc = cache->key.objectid; 1559 cache->last_alloc = cache->key.objectid;
@@ -1520,10 +1562,6 @@ int btrfs_read_block_groups(struct btrfs_root *root)
1520 cache->pinned = 0; 1562 cache->pinned = 0;
1521 cache->cached = 0; 1563 cache->cached = 0;
1522 1564
1523 if (nr % 3)
1524 cache->data = 1;
1525 else
1526 cache->data = 0;
1527 cache->radix = radix; 1565 cache->radix = radix;
1528 1566
1529 key.objectid = found_key.objectid + found_key.offset; 1567 key.objectid = found_key.objectid + found_key.offset;
@@ -1541,7 +1579,6 @@ int btrfs_read_block_groups(struct btrfs_root *root)
1541 if (key.objectid >= 1579 if (key.objectid >=
1542 btrfs_super_total_blocks(info->disk_super)) 1580 btrfs_super_total_blocks(info->disk_super))
1543 break; 1581 break;
1544 nr++;
1545 } 1582 }
1546 1583
1547 btrfs_free_path(path); 1584 btrfs_free_path(path);