diff options
-rw-r--r-- | fs/btrfs/ctree.h | 4 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 25 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 212 |
3 files changed, 50 insertions, 191 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index fd62aa856d1b..a07b8c0a260d 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1495,7 +1495,6 @@ struct btrfs_fs_info { | |||
1495 | int do_barriers; | 1495 | int do_barriers; |
1496 | int closing; | 1496 | int closing; |
1497 | int log_root_recovering; | 1497 | int log_root_recovering; |
1498 | int enospc_unlink; | ||
1499 | 1498 | ||
1500 | u64 total_pinned; | 1499 | u64 total_pinned; |
1501 | 1500 | ||
@@ -3183,6 +3182,9 @@ int btrfs_block_rsv_refill(struct btrfs_root *root, | |||
3183 | int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv, | 3182 | int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv, |
3184 | struct btrfs_block_rsv *dst_rsv, | 3183 | struct btrfs_block_rsv *dst_rsv, |
3185 | u64 num_bytes); | 3184 | u64 num_bytes); |
3185 | int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info, | ||
3186 | struct btrfs_block_rsv *dest, u64 num_bytes, | ||
3187 | int min_factor); | ||
3186 | void btrfs_block_rsv_release(struct btrfs_root *root, | 3188 | void btrfs_block_rsv_release(struct btrfs_root *root, |
3187 | struct btrfs_block_rsv *block_rsv, | 3189 | struct btrfs_block_rsv *block_rsv, |
3188 | u64 num_bytes); | 3190 | u64 num_bytes); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 4ec8305fe078..e14f8bd4b310 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -4297,6 +4297,31 @@ static void block_rsv_add_bytes(struct btrfs_block_rsv *block_rsv, | |||
4297 | spin_unlock(&block_rsv->lock); | 4297 | spin_unlock(&block_rsv->lock); |
4298 | } | 4298 | } |
4299 | 4299 | ||
4300 | int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info, | ||
4301 | struct btrfs_block_rsv *dest, u64 num_bytes, | ||
4302 | int min_factor) | ||
4303 | { | ||
4304 | struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; | ||
4305 | u64 min_bytes; | ||
4306 | |||
4307 | if (global_rsv->space_info != dest->space_info) | ||
4308 | return -ENOSPC; | ||
4309 | |||
4310 | spin_lock(&global_rsv->lock); | ||
4311 | min_bytes = div_factor(global_rsv->size, min_factor); | ||
4312 | if (global_rsv->reserved < min_bytes + num_bytes) { | ||
4313 | spin_unlock(&global_rsv->lock); | ||
4314 | return -ENOSPC; | ||
4315 | } | ||
4316 | global_rsv->reserved -= num_bytes; | ||
4317 | if (global_rsv->reserved < global_rsv->size) | ||
4318 | global_rsv->full = 0; | ||
4319 | spin_unlock(&global_rsv->lock); | ||
4320 | |||
4321 | block_rsv_add_bytes(dest, num_bytes, 1); | ||
4322 | return 0; | ||
4323 | } | ||
4324 | |||
4300 | static void block_rsv_release_bytes(struct btrfs_fs_info *fs_info, | 4325 | static void block_rsv_release_bytes(struct btrfs_fs_info *fs_info, |
4301 | struct btrfs_block_rsv *block_rsv, | 4326 | struct btrfs_block_rsv *block_rsv, |
4302 | struct btrfs_block_rsv *dest, u64 num_bytes) | 4327 | struct btrfs_block_rsv *dest, u64 num_bytes) |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 51520755f4dc..c0e95b1554a0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -3679,53 +3679,20 @@ int btrfs_unlink_inode(struct btrfs_trans_handle *trans, | |||
3679 | } | 3679 | } |
3680 | return ret; | 3680 | return ret; |
3681 | } | 3681 | } |
3682 | |||
3683 | |||
3684 | /* helper to check if there is any shared block in the path */ | ||
3685 | static int check_path_shared(struct btrfs_root *root, | ||
3686 | struct btrfs_path *path) | ||
3687 | { | ||
3688 | struct extent_buffer *eb; | ||
3689 | int level; | ||
3690 | u64 refs = 1; | ||
3691 | |||
3692 | for (level = 0; level < BTRFS_MAX_LEVEL; level++) { | ||
3693 | int ret; | ||
3694 | |||
3695 | if (!path->nodes[level]) | ||
3696 | break; | ||
3697 | eb = path->nodes[level]; | ||
3698 | if (!btrfs_block_can_be_shared(root, eb)) | ||
3699 | continue; | ||
3700 | ret = btrfs_lookup_extent_info(NULL, root, eb->start, level, 1, | ||
3701 | &refs, NULL); | ||
3702 | if (refs > 1) | ||
3703 | return 1; | ||
3704 | } | ||
3705 | return 0; | ||
3706 | } | ||
3707 | 3682 | ||
3708 | /* | 3683 | /* |
3709 | * helper to start transaction for unlink and rmdir. | 3684 | * helper to start transaction for unlink and rmdir. |
3710 | * | 3685 | * |
3711 | * unlink and rmdir are special in btrfs, they do not always free space. | 3686 | * unlink and rmdir are special in btrfs, they do not always free space, so |
3712 | * so in enospc case, we should make sure they will free space before | 3687 | * if we cannot make our reservations the normal way try and see if there is |
3713 | * allowing them to use the global metadata reservation. | 3688 | * plenty of slack room in the global reserve to migrate, otherwise we cannot |
3689 | * allow the unlink to occur. | ||
3714 | */ | 3690 | */ |
3715 | static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir, | 3691 | static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir) |
3716 | struct dentry *dentry) | ||
3717 | { | 3692 | { |
3718 | struct btrfs_trans_handle *trans; | 3693 | struct btrfs_trans_handle *trans; |
3719 | struct btrfs_root *root = BTRFS_I(dir)->root; | 3694 | struct btrfs_root *root = BTRFS_I(dir)->root; |
3720 | struct btrfs_path *path; | ||
3721 | struct btrfs_dir_item *di; | ||
3722 | struct inode *inode = dentry->d_inode; | ||
3723 | u64 index; | ||
3724 | int check_link = 1; | ||
3725 | int err = -ENOSPC; | ||
3726 | int ret; | 3695 | int ret; |
3727 | u64 ino = btrfs_ino(inode); | ||
3728 | u64 dir_ino = btrfs_ino(dir); | ||
3729 | 3696 | ||
3730 | /* | 3697 | /* |
3731 | * 1 for the possible orphan item | 3698 | * 1 for the possible orphan item |
@@ -3738,158 +3705,23 @@ static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir, | |||
3738 | if (!IS_ERR(trans) || PTR_ERR(trans) != -ENOSPC) | 3705 | if (!IS_ERR(trans) || PTR_ERR(trans) != -ENOSPC) |
3739 | return trans; | 3706 | return trans; |
3740 | 3707 | ||
3741 | if (ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) | 3708 | if (PTR_ERR(trans) == -ENOSPC) { |
3742 | return ERR_PTR(-ENOSPC); | 3709 | u64 num_bytes = btrfs_calc_trans_metadata_size(root, 5); |
3743 | |||
3744 | /* check if there is someone else holds reference */ | ||
3745 | if (S_ISDIR(inode->i_mode) && atomic_read(&inode->i_count) > 1) | ||
3746 | return ERR_PTR(-ENOSPC); | ||
3747 | |||
3748 | if (atomic_read(&inode->i_count) > 2) | ||
3749 | return ERR_PTR(-ENOSPC); | ||
3750 | |||
3751 | if (xchg(&root->fs_info->enospc_unlink, 1)) | ||
3752 | return ERR_PTR(-ENOSPC); | ||
3753 | |||
3754 | path = btrfs_alloc_path(); | ||
3755 | if (!path) { | ||
3756 | root->fs_info->enospc_unlink = 0; | ||
3757 | return ERR_PTR(-ENOMEM); | ||
3758 | } | ||
3759 | 3710 | ||
3760 | /* 1 for the orphan item */ | 3711 | trans = btrfs_start_transaction(root, 0); |
3761 | trans = btrfs_start_transaction(root, 1); | 3712 | if (IS_ERR(trans)) |
3762 | if (IS_ERR(trans)) { | 3713 | return trans; |
3763 | btrfs_free_path(path); | 3714 | ret = btrfs_cond_migrate_bytes(root->fs_info, |
3764 | root->fs_info->enospc_unlink = 0; | 3715 | &root->fs_info->trans_block_rsv, |
3765 | return trans; | 3716 | num_bytes, 5); |
3766 | } | 3717 | if (ret) { |
3767 | 3718 | btrfs_end_transaction(trans, root); | |
3768 | path->skip_locking = 1; | 3719 | return ERR_PTR(ret); |
3769 | path->search_commit_root = 1; | ||
3770 | |||
3771 | ret = btrfs_lookup_inode(trans, root, path, | ||
3772 | &BTRFS_I(dir)->location, 0); | ||
3773 | if (ret < 0) { | ||
3774 | err = ret; | ||
3775 | goto out; | ||
3776 | } | ||
3777 | if (ret == 0) { | ||
3778 | if (check_path_shared(root, path)) | ||
3779 | goto out; | ||
3780 | } else { | ||
3781 | check_link = 0; | ||
3782 | } | ||
3783 | btrfs_release_path(path); | ||
3784 | |||
3785 | ret = btrfs_lookup_inode(trans, root, path, | ||
3786 | &BTRFS_I(inode)->location, 0); | ||
3787 | if (ret < 0) { | ||
3788 | err = ret; | ||
3789 | goto out; | ||
3790 | } | ||
3791 | if (ret == 0) { | ||
3792 | if (check_path_shared(root, path)) | ||
3793 | goto out; | ||
3794 | } else { | ||
3795 | check_link = 0; | ||
3796 | } | ||
3797 | btrfs_release_path(path); | ||
3798 | |||
3799 | if (ret == 0 && S_ISREG(inode->i_mode)) { | ||
3800 | ret = btrfs_lookup_file_extent(trans, root, path, | ||
3801 | ino, (u64)-1, 0); | ||
3802 | if (ret < 0) { | ||
3803 | err = ret; | ||
3804 | goto out; | ||
3805 | } | 3720 | } |
3806 | BUG_ON(ret == 0); /* Corruption */ | ||
3807 | if (check_path_shared(root, path)) | ||
3808 | goto out; | ||
3809 | btrfs_release_path(path); | ||
3810 | } | ||
3811 | |||
3812 | if (!check_link) { | ||
3813 | err = 0; | ||
3814 | goto out; | ||
3815 | } | ||
3816 | |||
3817 | di = btrfs_lookup_dir_item(trans, root, path, dir_ino, | ||
3818 | dentry->d_name.name, dentry->d_name.len, 0); | ||
3819 | if (IS_ERR(di)) { | ||
3820 | err = PTR_ERR(di); | ||
3821 | goto out; | ||
3822 | } | ||
3823 | if (di) { | ||
3824 | if (check_path_shared(root, path)) | ||
3825 | goto out; | ||
3826 | } else { | ||
3827 | err = 0; | ||
3828 | goto out; | ||
3829 | } | ||
3830 | btrfs_release_path(path); | ||
3831 | |||
3832 | ret = btrfs_get_inode_ref_index(trans, root, path, dentry->d_name.name, | ||
3833 | dentry->d_name.len, ino, dir_ino, 0, | ||
3834 | &index); | ||
3835 | if (ret) { | ||
3836 | err = ret; | ||
3837 | goto out; | ||
3838 | } | ||
3839 | |||
3840 | if (check_path_shared(root, path)) | ||
3841 | goto out; | ||
3842 | |||
3843 | btrfs_release_path(path); | ||
3844 | |||
3845 | /* | ||
3846 | * This is a commit root search, if we can lookup inode item and other | ||
3847 | * relative items in the commit root, it means the transaction of | ||
3848 | * dir/file creation has been committed, and the dir index item that we | ||
3849 | * delay to insert has also been inserted into the commit root. So | ||
3850 | * we needn't worry about the delayed insertion of the dir index item | ||
3851 | * here. | ||
3852 | */ | ||
3853 | di = btrfs_lookup_dir_index_item(trans, root, path, dir_ino, index, | ||
3854 | dentry->d_name.name, dentry->d_name.len, 0); | ||
3855 | if (IS_ERR(di)) { | ||
3856 | err = PTR_ERR(di); | ||
3857 | goto out; | ||
3858 | } | ||
3859 | BUG_ON(ret == -ENOENT); | ||
3860 | if (check_path_shared(root, path)) | ||
3861 | goto out; | ||
3862 | |||
3863 | err = 0; | ||
3864 | out: | ||
3865 | btrfs_free_path(path); | ||
3866 | /* Migrate the orphan reservation over */ | ||
3867 | if (!err) | ||
3868 | err = btrfs_block_rsv_migrate(trans->block_rsv, | ||
3869 | &root->fs_info->global_block_rsv, | ||
3870 | trans->bytes_reserved); | ||
3871 | |||
3872 | if (err) { | ||
3873 | btrfs_end_transaction(trans, root); | ||
3874 | root->fs_info->enospc_unlink = 0; | ||
3875 | return ERR_PTR(err); | ||
3876 | } | ||
3877 | |||
3878 | trans->block_rsv = &root->fs_info->global_block_rsv; | ||
3879 | return trans; | ||
3880 | } | ||
3881 | |||
3882 | static void __unlink_end_trans(struct btrfs_trans_handle *trans, | ||
3883 | struct btrfs_root *root) | ||
3884 | { | ||
3885 | if (trans->block_rsv->type == BTRFS_BLOCK_RSV_GLOBAL) { | ||
3886 | btrfs_block_rsv_release(root, trans->block_rsv, | ||
3887 | trans->bytes_reserved); | ||
3888 | trans->block_rsv = &root->fs_info->trans_block_rsv; | 3721 | trans->block_rsv = &root->fs_info->trans_block_rsv; |
3889 | BUG_ON(!root->fs_info->enospc_unlink); | 3722 | trans->bytes_reserved = num_bytes; |
3890 | root->fs_info->enospc_unlink = 0; | ||
3891 | } | 3723 | } |
3892 | btrfs_end_transaction(trans, root); | 3724 | return trans; |
3893 | } | 3725 | } |
3894 | 3726 | ||
3895 | static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | 3727 | static int btrfs_unlink(struct inode *dir, struct dentry *dentry) |
@@ -3899,7 +3731,7 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
3899 | struct inode *inode = dentry->d_inode; | 3731 | struct inode *inode = dentry->d_inode; |
3900 | int ret; | 3732 | int ret; |
3901 | 3733 | ||
3902 | trans = __unlink_start_trans(dir, dentry); | 3734 | trans = __unlink_start_trans(dir); |
3903 | if (IS_ERR(trans)) | 3735 | if (IS_ERR(trans)) |
3904 | return PTR_ERR(trans); | 3736 | return PTR_ERR(trans); |
3905 | 3737 | ||
@@ -3917,7 +3749,7 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
3917 | } | 3749 | } |
3918 | 3750 | ||
3919 | out: | 3751 | out: |
3920 | __unlink_end_trans(trans, root); | 3752 | btrfs_end_transaction(trans, root); |
3921 | btrfs_btree_balance_dirty(root); | 3753 | btrfs_btree_balance_dirty(root); |
3922 | return ret; | 3754 | return ret; |
3923 | } | 3755 | } |
@@ -4014,7 +3846,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
4014 | if (btrfs_ino(inode) == BTRFS_FIRST_FREE_OBJECTID) | 3846 | if (btrfs_ino(inode) == BTRFS_FIRST_FREE_OBJECTID) |
4015 | return -EPERM; | 3847 | return -EPERM; |
4016 | 3848 | ||
4017 | trans = __unlink_start_trans(dir, dentry); | 3849 | trans = __unlink_start_trans(dir); |
4018 | if (IS_ERR(trans)) | 3850 | if (IS_ERR(trans)) |
4019 | return PTR_ERR(trans); | 3851 | return PTR_ERR(trans); |
4020 | 3852 | ||
@@ -4036,7 +3868,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
4036 | if (!err) | 3868 | if (!err) |
4037 | btrfs_i_size_write(inode, 0); | 3869 | btrfs_i_size_write(inode, 0); |
4038 | out: | 3870 | out: |
4039 | __unlink_end_trans(trans, root); | 3871 | btrfs_end_transaction(trans, root); |
4040 | btrfs_btree_balance_dirty(root); | 3872 | btrfs_btree_balance_dirty(root); |
4041 | 3873 | ||
4042 | return err; | 3874 | return err; |