aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-05-07 11:43:44 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:02 -0400
commita061fc8da7b990faa41ca503e66faef3ecdeead0 (patch)
tree0d3b5b6e4d2164d507d9a16d5b38d373592a5c8f /fs/btrfs/extent-tree.c
parent5d9cd9ecbf40b8bd5045a3c2f1feb35db6a12266 (diff)
Btrfs: Add support for online device removal
This required a few structural changes to the code that manages bdev pointers: The VFS super block now gets an anon-bdev instead of a pointer to the lowest bdev. This allows us to avoid swapping the super block bdev pointer around at run time. The code to read in the super block no longer goes through the extent buffer interface. Things got ugly keeping the mapping constant. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c139
1 files changed, 113 insertions, 26 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index f94794a99329..c0e67bde8428 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -147,6 +147,8 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
147 u64 end; 147 u64 end;
148 int ret; 148 int ret;
149 149
150 bytenr = max_t(u64, bytenr,
151 BTRFS_SUPER_INFO_OFFSET + BTRFS_SUPER_INFO_SIZE);
150 block_group_cache = &info->block_group_cache; 152 block_group_cache = &info->block_group_cache;
151 ret = find_first_extent_bit(block_group_cache, 153 ret = find_first_extent_bit(block_group_cache,
152 bytenr, &start, &end, 154 bytenr, &start, &end,
@@ -1059,16 +1061,25 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
1059 } 1061 }
1060} 1062}
1061 1063
1062static u64 reduce_alloc_profile(u64 flags) 1064static u64 reduce_alloc_profile(struct btrfs_root *root, u64 flags)
1063{ 1065{
1066 u64 num_devices = root->fs_info->fs_devices->num_devices;
1067
1068 if (num_devices == 1)
1069 flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0);
1070 if (num_devices < 4)
1071 flags &= ~BTRFS_BLOCK_GROUP_RAID10;
1072
1064 if ((flags & BTRFS_BLOCK_GROUP_DUP) && 1073 if ((flags & BTRFS_BLOCK_GROUP_DUP) &&
1065 (flags & (BTRFS_BLOCK_GROUP_RAID1 | 1074 (flags & (BTRFS_BLOCK_GROUP_RAID1 |
1066 BTRFS_BLOCK_GROUP_RAID10))) 1075 BTRFS_BLOCK_GROUP_RAID10))) {
1067 flags &= ~BTRFS_BLOCK_GROUP_DUP; 1076 flags &= ~BTRFS_BLOCK_GROUP_DUP;
1077 }
1068 1078
1069 if ((flags & BTRFS_BLOCK_GROUP_RAID1) && 1079 if ((flags & BTRFS_BLOCK_GROUP_RAID1) &&
1070 (flags & BTRFS_BLOCK_GROUP_RAID10)) 1080 (flags & BTRFS_BLOCK_GROUP_RAID10)) {
1071 flags &= ~BTRFS_BLOCK_GROUP_RAID1; 1081 flags &= ~BTRFS_BLOCK_GROUP_RAID1;
1082 }
1072 1083
1073 if ((flags & BTRFS_BLOCK_GROUP_RAID0) && 1084 if ((flags & BTRFS_BLOCK_GROUP_RAID0) &&
1074 ((flags & BTRFS_BLOCK_GROUP_RAID1) | 1085 ((flags & BTRFS_BLOCK_GROUP_RAID1) |
@@ -1078,7 +1089,6 @@ static u64 reduce_alloc_profile(u64 flags)
1078 return flags; 1089 return flags;
1079} 1090}
1080 1091
1081
1082static int do_chunk_alloc(struct btrfs_trans_handle *trans, 1092static int do_chunk_alloc(struct btrfs_trans_handle *trans,
1083 struct btrfs_root *extent_root, u64 alloc_bytes, 1093 struct btrfs_root *extent_root, u64 alloc_bytes,
1084 u64 flags) 1094 u64 flags)
@@ -1089,7 +1099,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
1089 u64 num_bytes; 1099 u64 num_bytes;
1090 int ret; 1100 int ret;
1091 1101
1092 flags = reduce_alloc_profile(flags); 1102 flags = reduce_alloc_profile(extent_root, flags);
1093 1103
1094 space_info = __find_space_info(extent_root->fs_info, flags); 1104 space_info = __find_space_info(extent_root->fs_info, flags);
1095 if (!space_info) { 1105 if (!space_info) {
@@ -1169,6 +1179,21 @@ static int update_block_group(struct btrfs_trans_handle *trans,
1169 return 0; 1179 return 0;
1170} 1180}
1171 1181
1182static u64 first_logical_byte(struct btrfs_root *root, u64 search_start)
1183{
1184 u64 start;
1185 u64 end;
1186 int ret;
1187 ret = find_first_extent_bit(&root->fs_info->block_group_cache,
1188 search_start, &start, &end,
1189 BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA |
1190 BLOCK_GROUP_SYSTEM);
1191 if (ret)
1192 return 0;
1193 return start;
1194}
1195
1196
1172static int update_pinned_extents(struct btrfs_root *root, 1197static int update_pinned_extents(struct btrfs_root *root,
1173 u64 bytenr, u64 num, int pin) 1198 u64 bytenr, u64 num, int pin)
1174{ 1199{
@@ -1185,16 +1210,25 @@ static int update_pinned_extents(struct btrfs_root *root,
1185 } 1210 }
1186 while (num > 0) { 1211 while (num > 0) {
1187 cache = btrfs_lookup_block_group(fs_info, bytenr); 1212 cache = btrfs_lookup_block_group(fs_info, bytenr);
1188 WARN_ON(!cache); 1213 if (!cache) {
1189 len = min(num, cache->key.offset - 1214 u64 first = first_logical_byte(root, bytenr);
1190 (bytenr - cache->key.objectid)); 1215 WARN_ON(first < bytenr);
1216 len = min(first - bytenr, num);
1217 } else {
1218 len = min(num, cache->key.offset -
1219 (bytenr - cache->key.objectid));
1220 }
1191 if (pin) { 1221 if (pin) {
1192 cache->pinned += len; 1222 if (cache) {
1193 cache->space_info->bytes_pinned += len; 1223 cache->pinned += len;
1224 cache->space_info->bytes_pinned += len;
1225 }
1194 fs_info->total_pinned += len; 1226 fs_info->total_pinned += len;
1195 } else { 1227 } else {
1196 cache->pinned -= len; 1228 if (cache) {
1197 cache->space_info->bytes_pinned -= len; 1229 cache->pinned -= len;
1230 cache->space_info->bytes_pinned -= len;
1231 }
1198 fs_info->total_pinned -= len; 1232 fs_info->total_pinned -= len;
1199 } 1233 }
1200 bytenr += len; 1234 bytenr += len;
@@ -1547,7 +1581,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
1547 int data) 1581 int data)
1548{ 1582{
1549 int ret; 1583 int ret;
1550 u64 orig_search_start = search_start; 1584 u64 orig_search_start;
1551 struct btrfs_root * root = orig_root->fs_info->extent_root; 1585 struct btrfs_root * root = orig_root->fs_info->extent_root;
1552 struct btrfs_fs_info *info = root->fs_info; 1586 struct btrfs_fs_info *info = root->fs_info;
1553 u64 total_needed = num_bytes; 1587 u64 total_needed = num_bytes;
@@ -1577,6 +1611,9 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
1577 } 1611 }
1578 } 1612 }
1579 1613
1614 search_start = max(search_start, first_logical_byte(root, 0));
1615 orig_search_start = search_start;
1616
1580 if (search_end == (u64)-1) 1617 if (search_end == (u64)-1)
1581 search_end = btrfs_super_total_bytes(&info->super_copy); 1618 search_end = btrfs_super_total_bytes(&info->super_copy);
1582 1619
@@ -1751,7 +1788,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1751 data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile; 1788 data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile;
1752 } 1789 }
1753again: 1790again:
1754 data = reduce_alloc_profile(data); 1791 data = reduce_alloc_profile(root, data);
1755 if (root->ref_cows) { 1792 if (root->ref_cows) {
1756 if (!(data & BTRFS_BLOCK_GROUP_METADATA)) { 1793 if (!(data & BTRFS_BLOCK_GROUP_METADATA)) {
1757 ret = do_chunk_alloc(trans, root->fs_info->extent_root, 1794 ret = do_chunk_alloc(trans, root->fs_info->extent_root,
@@ -2309,6 +2346,7 @@ static int noinline relocate_inode_pages(struct inode *inode, u64 start,
2309 struct file_ra_state *ra; 2346 struct file_ra_state *ra;
2310 unsigned long total_read = 0; 2347 unsigned long total_read = 0;
2311 unsigned long ra_pages; 2348 unsigned long ra_pages;
2349 struct btrfs_trans_handle *trans;
2312 2350
2313 ra = kzalloc(sizeof(*ra), GFP_NOFS); 2351 ra = kzalloc(sizeof(*ra), GFP_NOFS);
2314 2352
@@ -2326,9 +2364,13 @@ static int noinline relocate_inode_pages(struct inode *inode, u64 start,
2326 calc_ra(i, last_index, ra_pages)); 2364 calc_ra(i, last_index, ra_pages));
2327 } 2365 }
2328 total_read++; 2366 total_read++;
2367 if (((u64)i << PAGE_CACHE_SHIFT) > inode->i_size)
2368 goto truncate_racing;
2369
2329 page = grab_cache_page(inode->i_mapping, i); 2370 page = grab_cache_page(inode->i_mapping, i);
2330 if (!page) 2371 if (!page) {
2331 goto out_unlock; 2372 goto out_unlock;
2373 }
2332 if (!PageUptodate(page)) { 2374 if (!PageUptodate(page)) {
2333 btrfs_readpage(NULL, page); 2375 btrfs_readpage(NULL, page);
2334 lock_page(page); 2376 lock_page(page);
@@ -2350,20 +2392,33 @@ static int noinline relocate_inode_pages(struct inode *inode, u64 start,
2350 2392
2351 lock_extent(io_tree, page_start, page_end, GFP_NOFS); 2393 lock_extent(io_tree, page_start, page_end, GFP_NOFS);
2352 2394
2353 set_page_dirty(page);
2354 set_extent_delalloc(io_tree, page_start, 2395 set_extent_delalloc(io_tree, page_start,
2355 page_end, GFP_NOFS); 2396 page_end, GFP_NOFS);
2397 set_page_dirty(page);
2356 2398
2357 unlock_extent(io_tree, page_start, page_end, GFP_NOFS); 2399 unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
2358 unlock_page(page); 2400 unlock_page(page);
2359 page_cache_release(page); 2401 page_cache_release(page);
2360 balance_dirty_pages_ratelimited_nr(inode->i_mapping, 1);
2361 } 2402 }
2403 balance_dirty_pages_ratelimited_nr(inode->i_mapping,
2404 total_read);
2362 2405
2363out_unlock: 2406out_unlock:
2364 kfree(ra); 2407 kfree(ra);
2408 trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1);
2409 if (trans) {
2410 btrfs_add_ordered_inode(inode);
2411 btrfs_end_transaction(trans, BTRFS_I(inode)->root);
2412 mark_inode_dirty(inode);
2413 }
2365 mutex_unlock(&inode->i_mutex); 2414 mutex_unlock(&inode->i_mutex);
2366 return 0; 2415 return 0;
2416
2417truncate_racing:
2418 vmtruncate(inode, inode->i_size);
2419 balance_dirty_pages_ratelimited_nr(inode->i_mapping,
2420 total_read);
2421 goto out_unlock;
2367} 2422}
2368 2423
2369/* 2424/*
@@ -2466,6 +2521,27 @@ out:
2466 return 0; 2521 return 0;
2467} 2522}
2468 2523
2524static int noinline del_extent_zero(struct btrfs_root *extent_root,
2525 struct btrfs_path *path,
2526 struct btrfs_key *extent_key)
2527{
2528 int ret;
2529 struct btrfs_trans_handle *trans;
2530
2531 trans = btrfs_start_transaction(extent_root, 1);
2532 ret = btrfs_search_slot(trans, extent_root, extent_key, path, -1, 1);
2533 if (ret > 0) {
2534 ret = -EIO;
2535 goto out;
2536 }
2537 if (ret < 0)
2538 goto out;
2539 ret = btrfs_del_item(trans, extent_root, path);
2540out:
2541 btrfs_end_transaction(trans, extent_root);
2542 return ret;
2543}
2544
2469static int noinline relocate_one_extent(struct btrfs_root *extent_root, 2545static int noinline relocate_one_extent(struct btrfs_root *extent_root,
2470 struct btrfs_path *path, 2546 struct btrfs_path *path,
2471 struct btrfs_key *extent_key) 2547 struct btrfs_key *extent_key)
@@ -2477,6 +2553,10 @@ static int noinline relocate_one_extent(struct btrfs_root *extent_root,
2477 u32 item_size; 2553 u32 item_size;
2478 int ret = 0; 2554 int ret = 0;
2479 2555
2556 if (extent_key->objectid == 0) {
2557 ret = del_extent_zero(extent_root, path, extent_key);
2558 goto out;
2559 }
2480 key.objectid = extent_key->objectid; 2560 key.objectid = extent_key->objectid;
2481 key.type = BTRFS_EXTENT_REF_KEY; 2561 key.type = BTRFS_EXTENT_REF_KEY;
2482 key.offset = 0; 2562 key.offset = 0;
@@ -2490,15 +2570,24 @@ static int noinline relocate_one_extent(struct btrfs_root *extent_root,
2490 ret = 0; 2570 ret = 0;
2491 leaf = path->nodes[0]; 2571 leaf = path->nodes[0];
2492 nritems = btrfs_header_nritems(leaf); 2572 nritems = btrfs_header_nritems(leaf);
2493 if (path->slots[0] == nritems) 2573 if (path->slots[0] == nritems) {
2494 goto out; 2574 ret = btrfs_next_leaf(extent_root, path);
2575 if (ret > 0) {
2576 ret = 0;
2577 goto out;
2578 }
2579 if (ret < 0)
2580 goto out;
2581 }
2495 2582
2496 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 2583 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
2497 if (found_key.objectid != extent_key->objectid) 2584 if (found_key.objectid != extent_key->objectid) {
2498 break; 2585 break;
2586 }
2499 2587
2500 if (found_key.type != BTRFS_EXTENT_REF_KEY) 2588 if (found_key.type != BTRFS_EXTENT_REF_KEY) {
2501 break; 2589 break;
2590 }
2502 2591
2503 key.offset = found_key.offset + 1; 2592 key.offset = found_key.offset + 1;
2504 item_size = btrfs_item_size_nr(leaf, path->slots[0]); 2593 item_size = btrfs_item_size_nr(leaf, path->slots[0]);
@@ -2519,7 +2608,7 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
2519 u64 stripped = BTRFS_BLOCK_GROUP_RAID0 | 2608 u64 stripped = BTRFS_BLOCK_GROUP_RAID0 |
2520 BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; 2609 BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10;
2521 2610
2522 num_devices = btrfs_super_num_devices(&root->fs_info->super_copy); 2611 num_devices = root->fs_info->fs_devices->num_devices;
2523 if (num_devices == 1) { 2612 if (num_devices == 1) {
2524 stripped |= BTRFS_BLOCK_GROUP_DUP; 2613 stripped |= BTRFS_BLOCK_GROUP_DUP;
2525 stripped = flags & ~stripped; 2614 stripped = flags & ~stripped;
@@ -2535,9 +2624,6 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
2535 return flags; 2624 return flags;
2536 } else { 2625 } else {
2537 /* they already had raid on here, just return */ 2626 /* they already had raid on here, just return */
2538 if ((flags & BTRFS_BLOCK_GROUP_DUP) &&
2539 (flags & BTRFS_BLOCK_GROUP_RAID1)) {
2540 }
2541 if (flags & stripped) 2627 if (flags & stripped)
2542 return flags; 2628 return flags;
2543 2629
@@ -2570,7 +2656,7 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start)
2570 struct extent_buffer *leaf; 2656 struct extent_buffer *leaf;
2571 u32 nritems; 2657 u32 nritems;
2572 int ret; 2658 int ret;
2573 int progress = 0; 2659 int progress;
2574 2660
2575 shrink_block_group = btrfs_lookup_block_group(root->fs_info, 2661 shrink_block_group = btrfs_lookup_block_group(root->fs_info,
2576 shrink_start); 2662 shrink_start);
@@ -2597,6 +2683,7 @@ again:
2597 shrink_block_group->ro = 1; 2683 shrink_block_group->ro = 1;
2598 2684
2599 total_found = 0; 2685 total_found = 0;
2686 progress = 0;
2600 key.objectid = shrink_start; 2687 key.objectid = shrink_start;
2601 key.offset = 0; 2688 key.offset = 0;
2602 key.type = 0; 2689 key.type = 0;