aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-10-06 08:58:24 -0400
committerJosef Bacik <josef@redhat.com>2011-10-19 15:12:54 -0400
commit5b0e95bf607ddd59b39f52d3d55e6581c817b530 (patch)
treeda248f5492908ce8b9402beee68c6ee98aa3caed /fs/btrfs/extent-tree.c
parent9a82ca659d8bfd99afc0e89bbde2202322df5755 (diff)
Btrfs: inline checksums into the disk free space cache
Yeah yeah I know this is how we used to do it and then I changed it, but damnit I'm changing it back. The fact is that writing out checksums will modify metadata, which could cause us to dirty a block group we've already written out, so we have to truncate it and all of it's checksums and re-write it which will write new checksums which could dirty a blockg roup that has already been written and you see where I'm going with this? This can cause unmount or really anything that depends on a transaction to commit to take it's sweet damned time to happen. So go back to the way it was, only this time we're specifically setting NODATACOW because we can't go through the COW pathway anyway and we're doing our own built-in cow'ing by truncating the free space cache. The other new thing is once we truncate the old cache and preallocate the new space, we don't need to do that song and dance at all for the rest of the transaction, we can just overwrite the existing space with the new cache if the block group changes for whatever reason, and the NODATACOW will let us do this fine. So keep track of which transaction we last cleared our cache in and if we cleared it in this transaction just say we're all setup and carry on. This survives xfstests and stress.sh. The inode cache will continue to use the normal csum infrastructure since it only gets written once and there will be no more modifications to the fs tree in a transaction commit. Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index f95e55083bdb..0abf70c984e9 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2717,6 +2717,13 @@ again:
2717 goto again; 2717 goto again;
2718 } 2718 }
2719 2719
2720 /* We've already setup this transaction, go ahead and exit */
2721 if (block_group->cache_generation == trans->transid &&
2722 i_size_read(inode)) {
2723 dcs = BTRFS_DC_SETUP;
2724 goto out_put;
2725 }
2726
2720 /* 2727 /*
2721 * We want to set the generation to 0, that way if anything goes wrong 2728 * We want to set the generation to 0, that way if anything goes wrong
2722 * from here on out we know not to trust this cache when we load up next 2729 * from here on out we know not to trust this cache when we load up next
@@ -2756,19 +2763,16 @@ again:
2756 num_pages *= 16; 2763 num_pages *= 16;
2757 num_pages *= PAGE_CACHE_SIZE; 2764 num_pages *= PAGE_CACHE_SIZE;
2758 2765
2759 ret = btrfs_delalloc_reserve_space(inode, num_pages); 2766 ret = btrfs_check_data_free_space(inode, num_pages);
2760 if (ret) 2767 if (ret)
2761 goto out_put; 2768 goto out_put;
2762 2769
2763 ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages, 2770 ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages,
2764 num_pages, num_pages, 2771 num_pages, num_pages,
2765 &alloc_hint); 2772 &alloc_hint);
2766 if (!ret) { 2773 if (!ret)
2767 dcs = BTRFS_DC_SETUP; 2774 dcs = BTRFS_DC_SETUP;
2768 btrfs_free_reserved_data_space(inode, num_pages); 2775 btrfs_free_reserved_data_space(inode, num_pages);
2769 } else {
2770 btrfs_delalloc_release_space(inode, num_pages);
2771 }
2772 2776
2773out_put: 2777out_put:
2774 iput(inode); 2778 iput(inode);
@@ -2776,6 +2780,8 @@ out_free:
2776 btrfs_release_path(path); 2780 btrfs_release_path(path);
2777out: 2781out:
2778 spin_lock(&block_group->lock); 2782 spin_lock(&block_group->lock);
2783 if (!ret)
2784 block_group->cache_generation = trans->transid;
2779 block_group->disk_cache_state = dcs; 2785 block_group->disk_cache_state = dcs;
2780 spin_unlock(&block_group->lock); 2786 spin_unlock(&block_group->lock);
2781 2787