aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2010-06-21 14:48:16 -0400
committerJosef Bacik <josef@redhat.com>2010-10-28 15:59:09 -0400
commit0af3d00bad38d3bb9912a60928ad0669f17bdb76 (patch)
treeabbf4c773138a33dcde483ac60f016c4b5e55dcc /fs/btrfs/inode.c
parentf6f94e2ab1b33f0082ac22d71f66385a60d8157f (diff)
Btrfs: create special free space cache inode
In order to save free space cache, we need an inode to hold the data, and we need a special item to point at the right inode for the right block group. So first, create a special item that will point to the right inode, and the number of extent entries we will have and the number of bitmaps we will have. We truncate and pre-allocate space everytime to make sure it's uptodate. This feature will be turned on as soon as you mount with -o space_cache, however it is safe to boot into old kernels, they will just generate the cache the old fashion way. When you boot back into a newer kernel we will notice that we modified and not the cache and automatically discard the cache. Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c95
1 files changed, 78 insertions, 17 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c03864406af..1af1ea88e8a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1700,6 +1700,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
1700 ordered_extent->len); 1700 ordered_extent->len);
1701 BUG_ON(ret); 1701 BUG_ON(ret);
1702 } else { 1702 } else {
1703 BUG_ON(root == root->fs_info->tree_root);
1703 ret = insert_reserved_file_extent(trans, inode, 1704 ret = insert_reserved_file_extent(trans, inode,
1704 ordered_extent->file_offset, 1705 ordered_extent->file_offset,
1705 ordered_extent->start, 1706 ordered_extent->start,
@@ -3196,7 +3197,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
3196 3197
3197 BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY); 3198 BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
3198 3199
3199 if (root->ref_cows) 3200 if (root->ref_cows || root == root->fs_info->tree_root)
3200 btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0); 3201 btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0);
3201 3202
3202 path = btrfs_alloc_path(); 3203 path = btrfs_alloc_path();
@@ -3344,7 +3345,8 @@ delete:
3344 } else { 3345 } else {
3345 break; 3346 break;
3346 } 3347 }
3347 if (found_extent && root->ref_cows) { 3348 if (found_extent && (root->ref_cows ||
3349 root == root->fs_info->tree_root)) {
3348 btrfs_set_path_blocking(path); 3350 btrfs_set_path_blocking(path);
3349 ret = btrfs_free_extent(trans, root, extent_start, 3351 ret = btrfs_free_extent(trans, root, extent_start,
3350 extent_num_bytes, 0, 3352 extent_num_bytes, 0,
@@ -3675,7 +3677,8 @@ void btrfs_evict_inode(struct inode *inode)
3675 int ret; 3677 int ret;
3676 3678
3677 truncate_inode_pages(&inode->i_data, 0); 3679 truncate_inode_pages(&inode->i_data, 0);
3678 if (inode->i_nlink && btrfs_root_refs(&root->root_item) != 0) 3680 if (inode->i_nlink && (btrfs_root_refs(&root->root_item) != 0 ||
3681 root == root->fs_info->tree_root))
3679 goto no_delete; 3682 goto no_delete;
3680 3683
3681 if (is_bad_inode(inode)) { 3684 if (is_bad_inode(inode)) {
@@ -3888,7 +3891,14 @@ static void inode_tree_del(struct inode *inode)
3888 } 3891 }
3889 spin_unlock(&root->inode_lock); 3892 spin_unlock(&root->inode_lock);
3890 3893
3891 if (empty && btrfs_root_refs(&root->root_item) == 0) { 3894 /*
3895 * Free space cache has inodes in the tree root, but the tree root has a
3896 * root_refs of 0, so this could end up dropping the tree root as a
3897 * snapshot, so we need the extra !root->fs_info->tree_root check to
3898 * make sure we don't drop it.
3899 */
3900 if (empty && btrfs_root_refs(&root->root_item) == 0 &&
3901 root != root->fs_info->tree_root) {
3892 synchronize_srcu(&root->fs_info->subvol_srcu); 3902 synchronize_srcu(&root->fs_info->subvol_srcu);
3893 spin_lock(&root->inode_lock); 3903 spin_lock(&root->inode_lock);
3894 empty = RB_EMPTY_ROOT(&root->inode_tree); 3904 empty = RB_EMPTY_ROOT(&root->inode_tree);
@@ -4282,14 +4292,24 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc)
4282 struct btrfs_root *root = BTRFS_I(inode)->root; 4292 struct btrfs_root *root = BTRFS_I(inode)->root;
4283 struct btrfs_trans_handle *trans; 4293 struct btrfs_trans_handle *trans;
4284 int ret = 0; 4294 int ret = 0;
4295 bool nolock = false;
4285 4296
4286 if (BTRFS_I(inode)->dummy_inode) 4297 if (BTRFS_I(inode)->dummy_inode)
4287 return 0; 4298 return 0;
4288 4299
4300 smp_mb();
4301 nolock = (root->fs_info->closing && root == root->fs_info->tree_root);
4302
4289 if (wbc->sync_mode == WB_SYNC_ALL) { 4303 if (wbc->sync_mode == WB_SYNC_ALL) {
4290 trans = btrfs_join_transaction(root, 1); 4304 if (nolock)
4305 trans = btrfs_join_transaction_nolock(root, 1);
4306 else
4307 trans = btrfs_join_transaction(root, 1);
4291 btrfs_set_trans_block_group(trans, inode); 4308 btrfs_set_trans_block_group(trans, inode);
4292 ret = btrfs_commit_transaction(trans, root); 4309 if (nolock)
4310 ret = btrfs_end_transaction_nolock(trans, root);
4311 else
4312 ret = btrfs_commit_transaction(trans, root);
4293 } 4313 }
4294 return ret; 4314 return ret;
4295} 4315}
@@ -6308,6 +6328,21 @@ void btrfs_destroy_inode(struct inode *inode)
6308 spin_unlock(&root->fs_info->ordered_extent_lock); 6328 spin_unlock(&root->fs_info->ordered_extent_lock);
6309 } 6329 }
6310 6330
6331 if (root == root->fs_info->tree_root) {
6332 struct btrfs_block_group_cache *block_group;
6333
6334 block_group = btrfs_lookup_block_group(root->fs_info,
6335 BTRFS_I(inode)->block_group);
6336 if (block_group && block_group->inode == inode) {
6337 spin_lock(&block_group->lock);
6338 block_group->inode = NULL;
6339 spin_unlock(&block_group->lock);
6340 btrfs_put_block_group(block_group);
6341 } else if (block_group) {
6342 btrfs_put_block_group(block_group);
6343 }
6344 }
6345
6311 spin_lock(&root->orphan_lock); 6346 spin_lock(&root->orphan_lock);
6312 if (!list_empty(&BTRFS_I(inode)->i_orphan)) { 6347 if (!list_empty(&BTRFS_I(inode)->i_orphan)) {
6313 printk(KERN_INFO "BTRFS: inode %lu still on the orphan list\n", 6348 printk(KERN_INFO "BTRFS: inode %lu still on the orphan list\n",
@@ -6340,7 +6375,8 @@ int btrfs_drop_inode(struct inode *inode)
6340{ 6375{
6341 struct btrfs_root *root = BTRFS_I(inode)->root; 6376 struct btrfs_root *root = BTRFS_I(inode)->root;
6342 6377
6343 if (btrfs_root_refs(&root->root_item) == 0) 6378 if (btrfs_root_refs(&root->root_item) == 0 &&
6379 root != root->fs_info->tree_root)
6344 return 1; 6380 return 1;
6345 else 6381 else
6346 return generic_drop_inode(inode); 6382 return generic_drop_inode(inode);
@@ -6757,27 +6793,33 @@ out_unlock:
6757 return err; 6793 return err;
6758} 6794}
6759 6795
6760int btrfs_prealloc_file_range(struct inode *inode, int mode, 6796static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
6761 u64 start, u64 num_bytes, u64 min_size, 6797 u64 start, u64 num_bytes, u64 min_size,
6762 loff_t actual_len, u64 *alloc_hint) 6798 loff_t actual_len, u64 *alloc_hint,
6799 struct btrfs_trans_handle *trans)
6763{ 6800{
6764 struct btrfs_trans_handle *trans;
6765 struct btrfs_root *root = BTRFS_I(inode)->root; 6801 struct btrfs_root *root = BTRFS_I(inode)->root;
6766 struct btrfs_key ins; 6802 struct btrfs_key ins;
6767 u64 cur_offset = start; 6803 u64 cur_offset = start;
6768 int ret = 0; 6804 int ret = 0;
6805 bool own_trans = true;
6769 6806
6807 if (trans)
6808 own_trans = false;
6770 while (num_bytes > 0) { 6809 while (num_bytes > 0) {
6771 trans = btrfs_start_transaction(root, 3); 6810 if (own_trans) {
6772 if (IS_ERR(trans)) { 6811 trans = btrfs_start_transaction(root, 3);
6773 ret = PTR_ERR(trans); 6812 if (IS_ERR(trans)) {
6774 break; 6813 ret = PTR_ERR(trans);
6814 break;
6815 }
6775 } 6816 }
6776 6817
6777 ret = btrfs_reserve_extent(trans, root, num_bytes, min_size, 6818 ret = btrfs_reserve_extent(trans, root, num_bytes, min_size,
6778 0, *alloc_hint, (u64)-1, &ins, 1); 6819 0, *alloc_hint, (u64)-1, &ins, 1);
6779 if (ret) { 6820 if (ret) {
6780 btrfs_end_transaction(trans, root); 6821 if (own_trans)
6822 btrfs_end_transaction(trans, root);
6781 break; 6823 break;
6782 } 6824 }
6783 6825
@@ -6810,11 +6852,30 @@ int btrfs_prealloc_file_range(struct inode *inode, int mode,
6810 ret = btrfs_update_inode(trans, root, inode); 6852 ret = btrfs_update_inode(trans, root, inode);
6811 BUG_ON(ret); 6853 BUG_ON(ret);
6812 6854
6813 btrfs_end_transaction(trans, root); 6855 if (own_trans)
6856 btrfs_end_transaction(trans, root);
6814 } 6857 }
6815 return ret; 6858 return ret;
6816} 6859}
6817 6860
6861int btrfs_prealloc_file_range(struct inode *inode, int mode,
6862 u64 start, u64 num_bytes, u64 min_size,
6863 loff_t actual_len, u64 *alloc_hint)
6864{
6865 return __btrfs_prealloc_file_range(inode, mode, start, num_bytes,
6866 min_size, actual_len, alloc_hint,
6867 NULL);
6868}
6869
6870int btrfs_prealloc_file_range_trans(struct inode *inode,
6871 struct btrfs_trans_handle *trans, int mode,
6872 u64 start, u64 num_bytes, u64 min_size,
6873 loff_t actual_len, u64 *alloc_hint)
6874{
6875 return __btrfs_prealloc_file_range(inode, mode, start, num_bytes,
6876 min_size, actual_len, alloc_hint, trans);
6877}
6878
6818static long btrfs_fallocate(struct inode *inode, int mode, 6879static long btrfs_fallocate(struct inode *inode, int mode,
6819 loff_t offset, loff_t len) 6880 loff_t offset, loff_t len)
6820{ 6881{