diff options
Diffstat (limited to 'fs/ocfs2/refcounttree.c')
| -rw-r--r-- | fs/ocfs2/refcounttree.c | 69 |
1 files changed, 64 insertions, 5 deletions
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 60287fc56bcb..3a0df7a1b810 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
| @@ -3743,6 +3743,9 @@ static int ocfs2_attach_refcount_tree(struct inode *inode, | |||
| 3743 | goto out; | 3743 | goto out; |
| 3744 | } | 3744 | } |
| 3745 | 3745 | ||
| 3746 | if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) | ||
| 3747 | goto attach_xattr; | ||
| 3748 | |||
| 3746 | ocfs2_init_dinode_extent_tree(&di_et, INODE_CACHE(inode), di_bh); | 3749 | ocfs2_init_dinode_extent_tree(&di_et, INODE_CACHE(inode), di_bh); |
| 3747 | 3750 | ||
| 3748 | size = i_size_read(inode); | 3751 | size = i_size_read(inode); |
| @@ -3769,6 +3772,7 @@ static int ocfs2_attach_refcount_tree(struct inode *inode, | |||
| 3769 | cpos += num_clusters; | 3772 | cpos += num_clusters; |
| 3770 | } | 3773 | } |
| 3771 | 3774 | ||
| 3775 | attach_xattr: | ||
| 3772 | if (oi->ip_dyn_features & OCFS2_HAS_XATTR_FL) { | 3776 | if (oi->ip_dyn_features & OCFS2_HAS_XATTR_FL) { |
| 3773 | ret = ocfs2_xattr_attach_refcount_tree(inode, di_bh, | 3777 | ret = ocfs2_xattr_attach_refcount_tree(inode, di_bh, |
| 3774 | &ref_tree->rf_ci, | 3778 | &ref_tree->rf_ci, |
| @@ -3858,6 +3862,49 @@ out: | |||
| 3858 | return ret; | 3862 | return ret; |
| 3859 | } | 3863 | } |
| 3860 | 3864 | ||
| 3865 | static int ocfs2_duplicate_inline_data(struct inode *s_inode, | ||
| 3866 | struct buffer_head *s_bh, | ||
| 3867 | struct inode *t_inode, | ||
| 3868 | struct buffer_head *t_bh) | ||
| 3869 | { | ||
| 3870 | int ret; | ||
| 3871 | handle_t *handle; | ||
| 3872 | struct ocfs2_super *osb = OCFS2_SB(s_inode->i_sb); | ||
| 3873 | struct ocfs2_dinode *s_di = (struct ocfs2_dinode *)s_bh->b_data; | ||
| 3874 | struct ocfs2_dinode *t_di = (struct ocfs2_dinode *)t_bh->b_data; | ||
| 3875 | |||
| 3876 | BUG_ON(!(OCFS2_I(s_inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)); | ||
| 3877 | |||
| 3878 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | ||
| 3879 | if (IS_ERR(handle)) { | ||
| 3880 | ret = PTR_ERR(handle); | ||
| 3881 | mlog_errno(ret); | ||
| 3882 | goto out; | ||
| 3883 | } | ||
| 3884 | |||
| 3885 | ret = ocfs2_journal_access_di(handle, INODE_CACHE(t_inode), t_bh, | ||
| 3886 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 3887 | if (ret) { | ||
| 3888 | mlog_errno(ret); | ||
| 3889 | goto out_commit; | ||
| 3890 | } | ||
| 3891 | |||
| 3892 | t_di->id2.i_data.id_count = s_di->id2.i_data.id_count; | ||
| 3893 | memcpy(t_di->id2.i_data.id_data, s_di->id2.i_data.id_data, | ||
| 3894 | le16_to_cpu(s_di->id2.i_data.id_count)); | ||
| 3895 | spin_lock(&OCFS2_I(t_inode)->ip_lock); | ||
| 3896 | OCFS2_I(t_inode)->ip_dyn_features |= OCFS2_INLINE_DATA_FL; | ||
| 3897 | t_di->i_dyn_features = cpu_to_le16(OCFS2_I(t_inode)->ip_dyn_features); | ||
| 3898 | spin_unlock(&OCFS2_I(t_inode)->ip_lock); | ||
| 3899 | |||
| 3900 | ocfs2_journal_dirty(handle, t_bh); | ||
| 3901 | |||
| 3902 | out_commit: | ||
| 3903 | ocfs2_commit_trans(osb, handle); | ||
| 3904 | out: | ||
| 3905 | return ret; | ||
| 3906 | } | ||
| 3907 | |||
| 3861 | static int ocfs2_duplicate_extent_list(struct inode *s_inode, | 3908 | static int ocfs2_duplicate_extent_list(struct inode *s_inode, |
| 3862 | struct inode *t_inode, | 3909 | struct inode *t_inode, |
| 3863 | struct buffer_head *t_bh, | 3910 | struct buffer_head *t_bh, |
| @@ -3997,6 +4044,14 @@ static int ocfs2_create_reflink_node(struct inode *s_inode, | |||
| 3997 | goto out; | 4044 | goto out; |
| 3998 | } | 4045 | } |
| 3999 | 4046 | ||
| 4047 | if (OCFS2_I(s_inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
| 4048 | ret = ocfs2_duplicate_inline_data(s_inode, s_bh, | ||
| 4049 | t_inode, t_bh); | ||
| 4050 | if (ret) | ||
| 4051 | mlog_errno(ret); | ||
| 4052 | goto out; | ||
| 4053 | } | ||
| 4054 | |||
| 4000 | ret = ocfs2_lock_refcount_tree(osb, le64_to_cpu(di->i_refcount_loc), | 4055 | ret = ocfs2_lock_refcount_tree(osb, le64_to_cpu(di->i_refcount_loc), |
| 4001 | 1, &ref_tree, &ref_root_bh); | 4056 | 1, &ref_tree, &ref_root_bh); |
| 4002 | if (ret) { | 4057 | if (ret) { |
| @@ -4013,10 +4068,6 @@ static int ocfs2_create_reflink_node(struct inode *s_inode, | |||
| 4013 | goto out_unlock_refcount; | 4068 | goto out_unlock_refcount; |
| 4014 | } | 4069 | } |
| 4015 | 4070 | ||
| 4016 | ret = ocfs2_complete_reflink(s_inode, s_bh, t_inode, t_bh, preserve); | ||
| 4017 | if (ret) | ||
| 4018 | mlog_errno(ret); | ||
| 4019 | |||
| 4020 | out_unlock_refcount: | 4071 | out_unlock_refcount: |
| 4021 | ocfs2_unlock_refcount_tree(osb, ref_tree, 1); | 4072 | ocfs2_unlock_refcount_tree(osb, ref_tree, 1); |
| 4022 | brelse(ref_root_bh); | 4073 | brelse(ref_root_bh); |
| @@ -4068,9 +4119,17 @@ static int __ocfs2_reflink(struct dentry *old_dentry, | |||
| 4068 | ret = ocfs2_reflink_xattrs(inode, old_bh, | 4119 | ret = ocfs2_reflink_xattrs(inode, old_bh, |
| 4069 | new_inode, new_bh, | 4120 | new_inode, new_bh, |
| 4070 | preserve); | 4121 | preserve); |
| 4071 | if (ret) | 4122 | if (ret) { |
| 4072 | mlog_errno(ret); | 4123 | mlog_errno(ret); |
| 4124 | goto inode_unlock; | ||
| 4125 | } | ||
| 4073 | } | 4126 | } |
| 4127 | |||
| 4128 | ret = ocfs2_complete_reflink(inode, old_bh, | ||
| 4129 | new_inode, new_bh, preserve); | ||
| 4130 | if (ret) | ||
| 4131 | mlog_errno(ret); | ||
| 4132 | |||
| 4074 | inode_unlock: | 4133 | inode_unlock: |
| 4075 | ocfs2_inode_unlock(new_inode, 1); | 4134 | ocfs2_inode_unlock(new_inode, 1); |
| 4076 | brelse(new_bh); | 4135 | brelse(new_bh); |
