diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 139 |
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 | ||
1062 | static u64 reduce_alloc_profile(u64 flags) | 1064 | static 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 | |||
1082 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, | 1092 | static 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 | ||
1182 | static 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 | |||
1172 | static int update_pinned_extents(struct btrfs_root *root, | 1197 | static 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 | } |
1753 | again: | 1790 | again: |
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 | ||
2363 | out_unlock: | 2406 | out_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 | |||
2417 | truncate_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 | ||
2524 | static 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); | ||
2540 | out: | ||
2541 | btrfs_end_transaction(trans, extent_root); | ||
2542 | return ret; | ||
2543 | } | ||
2544 | |||
2469 | static int noinline relocate_one_extent(struct btrfs_root *extent_root, | 2545 | static 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; |