summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2014-06-18 22:42:50 -0400
committerChris Mason <clm@fb.com>2014-06-19 17:20:54 -0400
commite570fd27f2c5d7eac3876bccf99e9838d7f911a3 (patch)
tree3d73f4d8a2700fd441be0abe36cf7174bfb84c56 /fs/btrfs/inode.c
parent5349d6c3ffead27d693fdac21270541fa95ef33d (diff)
Btrfs: fix broken free space cache after the system crashed
When we mounted the filesystem after the crash, we got the following message: BTRFS error (device xxx): block group xxxx has wrong amount of free space BTRFS error (device xxx): failed to load free space cache for block group xxx It is because we didn't update the metadata of the allocated space (in extent tree) until the file data was written into the disk. During this time, there was no information about the allocated spaces in either the extent tree nor the free space cache. when we wrote out the free space cache at this time (commit transaction), those spaces were lost. In fact, only the free space that is used to store the file data had this problem, the others didn't because the metadata of them is updated in the same transaction context. There are many methods which can fix the above problem - track the allocated space, and write it out when we write out the free space cache - account the size of the allocated space that is used to store the file data, if the size is not zero, don't write out the free space cache. The first one is complex and may make the performance drop down. This patch chose the second method, we use a per-block-group variant to account the size of that allocated space. Besides that, we also introduce a per-block-group read-write semaphore to avoid the race between the allocation and the free space cache write out. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 372b2cb2b297..6b65fab27a1a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -693,7 +693,7 @@ retry:
693 ret = btrfs_reserve_extent(root, 693 ret = btrfs_reserve_extent(root,
694 async_extent->compressed_size, 694 async_extent->compressed_size,
695 async_extent->compressed_size, 695 async_extent->compressed_size,
696 0, alloc_hint, &ins, 1); 696 0, alloc_hint, &ins, 1, 1);
697 if (ret) { 697 if (ret) {
698 int i; 698 int i;
699 699
@@ -794,7 +794,7 @@ retry:
794out: 794out:
795 return ret; 795 return ret;
796out_free_reserve: 796out_free_reserve:
797 btrfs_free_reserved_extent(root, ins.objectid, ins.offset); 797 btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1);
798out_free: 798out_free:
799 extent_clear_unlock_delalloc(inode, async_extent->start, 799 extent_clear_unlock_delalloc(inode, async_extent->start,
800 async_extent->start + 800 async_extent->start +
@@ -917,7 +917,7 @@ static noinline int cow_file_range(struct inode *inode,
917 cur_alloc_size = disk_num_bytes; 917 cur_alloc_size = disk_num_bytes;
918 ret = btrfs_reserve_extent(root, cur_alloc_size, 918 ret = btrfs_reserve_extent(root, cur_alloc_size,
919 root->sectorsize, 0, alloc_hint, 919 root->sectorsize, 0, alloc_hint,
920 &ins, 1); 920 &ins, 1, 1);
921 if (ret < 0) 921 if (ret < 0)
922 goto out_unlock; 922 goto out_unlock;
923 923
@@ -995,7 +995,7 @@ out:
995 return ret; 995 return ret;
996 996
997out_reserve: 997out_reserve:
998 btrfs_free_reserved_extent(root, ins.objectid, ins.offset); 998 btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1);
999out_unlock: 999out_unlock:
1000 extent_clear_unlock_delalloc(inode, start, end, locked_page, 1000 extent_clear_unlock_delalloc(inode, start, end, locked_page,
1001 EXTENT_LOCKED | EXTENT_DO_ACCOUNTING | 1001 EXTENT_LOCKED | EXTENT_DO_ACCOUNTING |
@@ -2599,6 +2599,21 @@ out_kfree:
2599 return NULL; 2599 return NULL;
2600} 2600}
2601 2601
2602static void btrfs_release_delalloc_bytes(struct btrfs_root *root,
2603 u64 start, u64 len)
2604{
2605 struct btrfs_block_group_cache *cache;
2606
2607 cache = btrfs_lookup_block_group(root->fs_info, start);
2608 ASSERT(cache);
2609
2610 spin_lock(&cache->lock);
2611 cache->delalloc_bytes -= len;
2612 spin_unlock(&cache->lock);
2613
2614 btrfs_put_block_group(cache);
2615}
2616
2602/* as ordered data IO finishes, this gets called so we can finish 2617/* as ordered data IO finishes, this gets called so we can finish
2603 * an ordered extent if the range of bytes in the file it covers are 2618 * an ordered extent if the range of bytes in the file it covers are
2604 * fully written. 2619 * fully written.
@@ -2698,6 +2713,10 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
2698 logical_len, logical_len, 2713 logical_len, logical_len,
2699 compress_type, 0, 0, 2714 compress_type, 0, 0,
2700 BTRFS_FILE_EXTENT_REG); 2715 BTRFS_FILE_EXTENT_REG);
2716 if (!ret)
2717 btrfs_release_delalloc_bytes(root,
2718 ordered_extent->start,
2719 ordered_extent->disk_len);
2701 } 2720 }
2702 unpin_extent_cache(&BTRFS_I(inode)->extent_tree, 2721 unpin_extent_cache(&BTRFS_I(inode)->extent_tree,
2703 ordered_extent->file_offset, ordered_extent->len, 2722 ordered_extent->file_offset, ordered_extent->len,
@@ -2750,7 +2769,7 @@ out:
2750 !test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags) && 2769 !test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags) &&
2751 !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) 2770 !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags))
2752 btrfs_free_reserved_extent(root, ordered_extent->start, 2771 btrfs_free_reserved_extent(root, ordered_extent->start,
2753 ordered_extent->disk_len); 2772 ordered_extent->disk_len, 1);
2754 } 2773 }
2755 2774
2756 2775
@@ -6535,21 +6554,21 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
6535 6554
6536 alloc_hint = get_extent_allocation_hint(inode, start, len); 6555 alloc_hint = get_extent_allocation_hint(inode, start, len);
6537 ret = btrfs_reserve_extent(root, len, root->sectorsize, 0, 6556 ret = btrfs_reserve_extent(root, len, root->sectorsize, 0,
6538 alloc_hint, &ins, 1); 6557 alloc_hint, &ins, 1, 1);
6539 if (ret) 6558 if (ret)
6540 return ERR_PTR(ret); 6559 return ERR_PTR(ret);
6541 6560
6542 em = create_pinned_em(inode, start, ins.offset, start, ins.objectid, 6561 em = create_pinned_em(inode, start, ins.offset, start, ins.objectid,
6543 ins.offset, ins.offset, ins.offset, 0); 6562 ins.offset, ins.offset, ins.offset, 0);
6544 if (IS_ERR(em)) { 6563 if (IS_ERR(em)) {
6545 btrfs_free_reserved_extent(root, ins.objectid, ins.offset); 6564 btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1);
6546 return em; 6565 return em;
6547 } 6566 }
6548 6567
6549 ret = btrfs_add_ordered_extent_dio(inode, start, ins.objectid, 6568 ret = btrfs_add_ordered_extent_dio(inode, start, ins.objectid,
6550 ins.offset, ins.offset, 0); 6569 ins.offset, ins.offset, 0);
6551 if (ret) { 6570 if (ret) {
6552 btrfs_free_reserved_extent(root, ins.objectid, ins.offset); 6571 btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1);
6553 free_extent_map(em); 6572 free_extent_map(em);
6554 return ERR_PTR(ret); 6573 return ERR_PTR(ret);
6555 } 6574 }
@@ -7437,7 +7456,7 @@ free_ordered:
7437 if (!test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags) && 7456 if (!test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags) &&
7438 !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) 7457 !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags))
7439 btrfs_free_reserved_extent(root, ordered->start, 7458 btrfs_free_reserved_extent(root, ordered->start,
7440 ordered->disk_len); 7459 ordered->disk_len, 1);
7441 btrfs_put_ordered_extent(ordered); 7460 btrfs_put_ordered_extent(ordered);
7442 btrfs_put_ordered_extent(ordered); 7461 btrfs_put_ordered_extent(ordered);
7443 } 7462 }
@@ -8819,7 +8838,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
8819 cur_bytes = min(num_bytes, 256ULL * 1024 * 1024); 8838 cur_bytes = min(num_bytes, 256ULL * 1024 * 1024);
8820 cur_bytes = max(cur_bytes, min_size); 8839 cur_bytes = max(cur_bytes, min_size);
8821 ret = btrfs_reserve_extent(root, cur_bytes, min_size, 0, 8840 ret = btrfs_reserve_extent(root, cur_bytes, min_size, 0,
8822 *alloc_hint, &ins, 1); 8841 *alloc_hint, &ins, 1, 0);
8823 if (ret) { 8842 if (ret) {
8824 if (own_trans) 8843 if (own_trans)
8825 btrfs_end_transaction(trans, root); 8844 btrfs_end_transaction(trans, root);
@@ -8833,7 +8852,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
8833 BTRFS_FILE_EXTENT_PREALLOC); 8852 BTRFS_FILE_EXTENT_PREALLOC);
8834 if (ret) { 8853 if (ret) {
8835 btrfs_free_reserved_extent(root, ins.objectid, 8854 btrfs_free_reserved_extent(root, ins.objectid,
8836 ins.offset); 8855 ins.offset, 0);
8837 btrfs_abort_transaction(trans, root, ret); 8856 btrfs_abort_transaction(trans, root, ret);
8838 if (own_trans) 8857 if (own_trans)
8839 btrfs_end_transaction(trans, root); 8858 btrfs_end_transaction(trans, root);