aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTao Ma <tao.ma@oracle.com>2009-08-17 23:43:55 -0400
committerJoel Becker <joel.becker@oracle.com>2009-09-22 23:09:45 -0400
commit2999d12f4d5529b282ce201b21444590c3f9f723 (patch)
tree9500f897753a59cf47e66af2cb7fd56c05ec8c1c
parenta7fe7a3a1ab5dac8d81e531c060f51e12010133b (diff)
ocfs2: Add reflink support for xattr.
Signed-off-by: Tao Ma <tao.ma@oracle.com>
-rw-r--r--fs/ocfs2/refcounttree.c24
-rw-r--r--fs/ocfs2/refcounttree.h6
-rw-r--r--fs/ocfs2/xattr.c923
-rw-r--r--fs/ocfs2/xattr.h4
4 files changed, 945 insertions, 12 deletions
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index 5656c68a2cae..dc57d066f794 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -1894,12 +1894,12 @@ out:
1894 return ret; 1894 return ret;
1895} 1895}
1896 1896
1897static int __ocfs2_increase_refcount(handle_t *handle, 1897int ocfs2_increase_refcount(handle_t *handle,
1898 struct ocfs2_caching_info *ci, 1898 struct ocfs2_caching_info *ci,
1899 struct buffer_head *ref_root_bh, 1899 struct buffer_head *ref_root_bh,
1900 u64 cpos, u32 len, 1900 u64 cpos, u32 len,
1901 struct ocfs2_alloc_context *meta_ac, 1901 struct ocfs2_alloc_context *meta_ac,
1902 struct ocfs2_cached_dealloc_ctxt *dealloc) 1902 struct ocfs2_cached_dealloc_ctxt *dealloc)
1903{ 1903{
1904 int ret = 0, index; 1904 int ret = 0, index;
1905 struct buffer_head *ref_leaf_bh = NULL; 1905 struct buffer_head *ref_leaf_bh = NULL;
@@ -3631,9 +3631,9 @@ int ocfs2_add_refcount_flag(struct inode *inode,
3631 goto out_commit; 3631 goto out_commit;
3632 } 3632 }
3633 3633
3634 ret = __ocfs2_increase_refcount(handle, ref_ci, ref_root_bh, 3634 ret = ocfs2_increase_refcount(handle, ref_ci, ref_root_bh,
3635 p_cluster, num_clusters, 3635 p_cluster, num_clusters,
3636 meta_ac, dealloc); 3636 meta_ac, dealloc);
3637 if (ret) { 3637 if (ret) {
3638 mlog_errno(ret); 3638 mlog_errno(ret);
3639 goto out_commit; 3639 goto out_commit;
@@ -3822,9 +3822,9 @@ static int ocfs2_add_refcounted_extent(struct inode *inode,
3822 goto out_commit; 3822 goto out_commit;
3823 } 3823 }
3824 3824
3825 ret = __ocfs2_increase_refcount(handle, ref_ci, ref_root_bh, 3825 ret = ocfs2_increase_refcount(handle, ref_ci, ref_root_bh,
3826 p_cluster, num_clusters, 3826 p_cluster, num_clusters,
3827 meta_ac, dealloc); 3827 meta_ac, dealloc);
3828 if (ret) 3828 if (ret)
3829 mlog_errno(ret); 3829 mlog_errno(ret);
3830 3830
diff --git a/fs/ocfs2/refcounttree.h b/fs/ocfs2/refcounttree.h
index 1e3446a655dd..2c238e682570 100644
--- a/fs/ocfs2/refcounttree.h
+++ b/fs/ocfs2/refcounttree.h
@@ -93,4 +93,10 @@ int ocfs2_add_refcount_flag(struct inode *inode,
93int ocfs2_remove_refcount_tree(struct inode *inode, struct buffer_head *di_bh); 93int ocfs2_remove_refcount_tree(struct inode *inode, struct buffer_head *di_bh);
94int ocfs2_try_remove_refcount_tree(struct inode *inode, 94int ocfs2_try_remove_refcount_tree(struct inode *inode,
95 struct buffer_head *di_bh); 95 struct buffer_head *di_bh);
96int ocfs2_increase_refcount(handle_t *handle,
97 struct ocfs2_caching_info *ci,
98 struct buffer_head *ref_root_bh,
99 u64 cpos, u32 len,
100 struct ocfs2_alloc_context *meta_ac,
101 struct ocfs2_cached_dealloc_ctxt *dealloc);
96#endif /* OCFS2_REFCOUNTTREE_H */ 102#endif /* OCFS2_REFCOUNTTREE_H */
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index bb92a6d274c0..661ed9b85dbf 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -5877,6 +5877,929 @@ out:
5877} 5877}
5878 5878
5879/* 5879/*
5880 * Store the information we need in xattr reflink.
5881 * old_bh and new_bh are inode bh for the old and new inode.
5882 */
5883struct ocfs2_xattr_reflink {
5884 struct inode *old_inode;
5885 struct inode *new_inode;
5886 struct buffer_head *old_bh;
5887 struct buffer_head *new_bh;
5888 struct ocfs2_caching_info *ref_ci;
5889 struct buffer_head *ref_root_bh;
5890 struct ocfs2_cached_dealloc_ctxt *dealloc;
5891};
5892
5893/*
5894 * Given a xattr header and xe offset,
5895 * return the proper xv and the corresponding bh.
5896 * xattr in inode, block and xattr tree have different implementaions.
5897 */
5898typedef int (get_xattr_value_root)(struct super_block *sb,
5899 struct buffer_head *bh,
5900 struct ocfs2_xattr_header *xh,
5901 int offset,
5902 struct ocfs2_xattr_value_root **xv,
5903 struct buffer_head **ret_bh,
5904 void *para);
5905
5906/*
5907 * Calculate all the xattr value root metadata stored in this xattr header and
5908 * credits we need if we create them from the scratch.
5909 * We use get_xattr_value_root so that all types of xattr container can use it.
5910 */
5911static int ocfs2_value_metas_in_xattr_header(struct super_block *sb,
5912 struct buffer_head *bh,
5913 struct ocfs2_xattr_header *xh,
5914 int *metas, int *credits,
5915 int *num_recs,
5916 get_xattr_value_root *func,
5917 void *para)
5918{
5919 int i, ret = 0;
5920 struct ocfs2_xattr_value_root *xv;
5921 struct ocfs2_xattr_entry *xe;
5922
5923 for (i = 0; i < le16_to_cpu(xh->xh_count); i++) {
5924 xe = &xh->xh_entries[i];
5925 if (ocfs2_xattr_is_local(xe))
5926 continue;
5927
5928 ret = func(sb, bh, xh, i, &xv, NULL, para);
5929 if (ret) {
5930 mlog_errno(ret);
5931 break;
5932 }
5933
5934 *metas += le16_to_cpu(xv->xr_list.l_tree_depth) *
5935 le16_to_cpu(xv->xr_list.l_next_free_rec);
5936
5937 *credits += ocfs2_calc_extend_credits(sb,
5938 &def_xv.xv.xr_list,
5939 le32_to_cpu(xv->xr_clusters));
5940
5941 /*
5942 * If the value is a tree with depth > 1, We don't go deep
5943 * to the extent block, so just calculate a maximum record num.
5944 */
5945 if (!xv->xr_list.l_tree_depth)
5946 *num_recs += xv->xr_list.l_next_free_rec;
5947 else
5948 *num_recs += ocfs2_clusters_for_bytes(sb,
5949 XATTR_SIZE_MAX);
5950 }
5951
5952 return ret;
5953}
5954
5955/* Used by xattr inode and block to return the right xv and buffer_head. */
5956static int ocfs2_get_xattr_value_root(struct super_block *sb,
5957 struct buffer_head *bh,
5958 struct ocfs2_xattr_header *xh,
5959 int offset,
5960 struct ocfs2_xattr_value_root **xv,
5961 struct buffer_head **ret_bh,
5962 void *para)
5963{
5964 struct ocfs2_xattr_entry *xe = &xh->xh_entries[offset];
5965
5966 *xv = (struct ocfs2_xattr_value_root *)((void *)xh +
5967 le16_to_cpu(xe->xe_name_offset) +
5968 OCFS2_XATTR_SIZE(xe->xe_name_len));
5969
5970 if (ret_bh)
5971 *ret_bh = bh;
5972
5973 return 0;
5974}
5975
5976/*
5977 * Lock the meta_ac and caculate how much credits we need for reflink xattrs.
5978 * It is only used for inline xattr and xattr block.
5979 */
5980static int ocfs2_reflink_lock_xattr_allocators(struct ocfs2_super *osb,
5981 struct ocfs2_xattr_header *xh,
5982 struct buffer_head *ref_root_bh,
5983 int *credits,
5984 struct ocfs2_alloc_context **meta_ac)
5985{
5986 int ret, meta_add = 0, num_recs = 0;
5987 struct ocfs2_refcount_block *rb =
5988 (struct ocfs2_refcount_block *)ref_root_bh->b_data;
5989
5990 *credits = 0;
5991
5992 ret = ocfs2_value_metas_in_xattr_header(osb->sb, NULL, xh,
5993 &meta_add, credits, &num_recs,
5994 ocfs2_get_xattr_value_root,
5995 NULL);
5996 if (ret) {
5997 mlog_errno(ret);
5998 goto out;
5999 }
6000
6001 /*
6002 * We need to add/modify num_recs in refcount tree, so just calculate
6003 * an approximate number we need for refcount tree change.
6004 * Sometimes we need to split the tree, and after split, half recs
6005 * will be moved to the new block, and a new block can only provide
6006 * half number of recs. So we multiple new blocks by 2.
6007 */
6008 num_recs = num_recs / ocfs2_refcount_recs_per_rb(osb->sb) * 2;
6009 meta_add += num_recs;
6010 *credits += num_recs + num_recs * OCFS2_EXPAND_REFCOUNT_TREE_CREDITS;
6011 if (le32_to_cpu(rb->rf_flags) & OCFS2_REFCOUNT_TREE_FL)
6012 *credits += le16_to_cpu(rb->rf_list.l_tree_depth) *
6013 le16_to_cpu(rb->rf_list.l_next_free_rec) + 1;
6014 else
6015 *credits += 1;
6016
6017 ret = ocfs2_reserve_new_metadata_blocks(osb, meta_add, meta_ac);
6018 if (ret)
6019 mlog_errno(ret);
6020
6021out:
6022 return ret;
6023}
6024
6025/*
6026 * Given a xattr header, reflink all the xattrs in this container.
6027 * It can be used for inode, block and bucket.
6028 *
6029 * NOTE:
6030 * Before we call this function, the caller has memcpy the xattr in
6031 * old_xh to the new_xh.
6032 */
6033static int ocfs2_reflink_xattr_header(handle_t *handle,
6034 struct ocfs2_xattr_reflink *args,
6035 struct buffer_head *old_bh,
6036 struct ocfs2_xattr_header *xh,
6037 struct buffer_head *new_bh,
6038 struct ocfs2_xattr_header *new_xh,
6039 struct ocfs2_xattr_value_buf *vb,
6040 struct ocfs2_alloc_context *meta_ac,
6041 get_xattr_value_root *func,
6042 void *para)
6043{
6044 int ret = 0, i;
6045 struct super_block *sb = args->old_inode->i_sb;
6046 struct buffer_head *value_bh;
6047 struct ocfs2_xattr_entry *xe;
6048 struct ocfs2_xattr_value_root *xv, *new_xv;
6049 struct ocfs2_extent_tree data_et;
6050 u32 clusters, cpos, p_cluster, num_clusters;
6051 unsigned int ext_flags = 0;
6052
6053 mlog(0, "reflink xattr in container %llu, count = %u\n",
6054 (unsigned long long)old_bh->b_blocknr, le16_to_cpu(xh->xh_count));
6055 for (i = 0; i < le16_to_cpu(xh->xh_count); i++) {
6056 xe = &xh->xh_entries[i];
6057
6058 if (ocfs2_xattr_is_local(xe))
6059 continue;
6060
6061 ret = func(sb, old_bh, xh, i, &xv, NULL, para);
6062 if (ret) {
6063 mlog_errno(ret);
6064 break;
6065 }
6066
6067 ret = func(sb, new_bh, new_xh, i, &new_xv, &value_bh, para);
6068 if (ret) {
6069 mlog_errno(ret);
6070 break;
6071 }
6072
6073 /*
6074 * For the xattr which has l_tree_depth = 0, all the extent
6075 * recs have already be copied to the new xh with the
6076 * propriate OCFS2_EXT_REFCOUNTED flag we just need to
6077 * increase the refount count int the refcount tree.
6078 *
6079 * For the xattr which has l_tree_depth > 0, we need
6080 * to initialize it to the empty default value root,
6081 * and then insert the extents one by one.
6082 */
6083 if (xv->xr_list.l_tree_depth) {
6084 memcpy(new_xv, &def_xv, sizeof(def_xv));
6085 vb->vb_xv = new_xv;
6086 vb->vb_bh = value_bh;
6087 ocfs2_init_xattr_value_extent_tree(&data_et,
6088 INODE_CACHE(args->new_inode), vb);
6089 }
6090
6091 clusters = le32_to_cpu(xv->xr_clusters);
6092 cpos = 0;
6093 while (cpos < clusters) {
6094 ret = ocfs2_xattr_get_clusters(args->old_inode,
6095 cpos,
6096 &p_cluster,
6097 &num_clusters,
6098 &xv->xr_list,
6099 &ext_flags);
6100 if (ret) {
6101 mlog_errno(ret);
6102 goto out;
6103 }
6104
6105 BUG_ON(!p_cluster);
6106
6107 if (xv->xr_list.l_tree_depth) {
6108 ret = ocfs2_insert_extent(handle,
6109 &data_et, cpos,
6110 ocfs2_clusters_to_blocks(
6111 args->old_inode->i_sb,
6112 p_cluster),
6113 num_clusters, ext_flags,
6114 meta_ac);
6115 if (ret) {
6116 mlog_errno(ret);
6117 goto out;
6118 }
6119 }
6120
6121 ret = ocfs2_increase_refcount(handle, args->ref_ci,
6122 args->ref_root_bh,
6123 p_cluster, num_clusters,
6124 meta_ac, args->dealloc);
6125 if (ret) {
6126 mlog_errno(ret);
6127 goto out;
6128 }
6129
6130 cpos += num_clusters;
6131 }
6132 }
6133
6134out:
6135 return ret;
6136}
6137
6138static int ocfs2_reflink_xattr_inline(struct ocfs2_xattr_reflink *args)
6139{
6140 int ret = 0, credits = 0;
6141 handle_t *handle;
6142 struct ocfs2_super *osb = OCFS2_SB(args->old_inode->i_sb);
6143 struct ocfs2_dinode *di = (struct ocfs2_dinode *)args->old_bh->b_data;
6144 int inline_size = le16_to_cpu(di->i_xattr_inline_size);
6145 int header_off = osb->sb->s_blocksize - inline_size;
6146 struct ocfs2_xattr_header *xh = (struct ocfs2_xattr_header *)
6147 (args->old_bh->b_data + header_off);
6148 struct ocfs2_xattr_header *new_xh = (struct ocfs2_xattr_header *)
6149 (args->new_bh->b_data + header_off);
6150 struct ocfs2_alloc_context *meta_ac = NULL;
6151 struct ocfs2_inode_info *new_oi;
6152 struct ocfs2_dinode *new_di;
6153 struct ocfs2_xattr_value_buf vb = {
6154 .vb_bh = args->new_bh,
6155 .vb_access = ocfs2_journal_access_di,
6156 };
6157
6158 ret = ocfs2_reflink_lock_xattr_allocators(osb, xh, args->ref_root_bh,
6159 &credits, &meta_ac);
6160 if (ret) {
6161 mlog_errno(ret);
6162 goto out;
6163 }
6164
6165 handle = ocfs2_start_trans(osb, credits);
6166 if (IS_ERR(handle)) {
6167 ret = PTR_ERR(handle);
6168 mlog_errno(ret);
6169 goto out;
6170 }
6171
6172 ret = ocfs2_journal_access_di(handle, INODE_CACHE(args->new_inode),
6173 args->new_bh, OCFS2_JOURNAL_ACCESS_WRITE);
6174 if (ret) {
6175 mlog_errno(ret);
6176 goto out_commit;
6177 }
6178
6179 memcpy(args->new_bh->b_data + header_off,
6180 args->old_bh->b_data + header_off, inline_size);
6181
6182 new_di = (struct ocfs2_dinode *)args->new_bh->b_data;
6183 new_di->i_xattr_inline_size = cpu_to_le16(inline_size);
6184
6185 ret = ocfs2_reflink_xattr_header(handle, args, args->old_bh, xh,
6186 args->new_bh, new_xh, &vb, meta_ac,
6187 ocfs2_get_xattr_value_root, NULL);
6188 if (ret) {
6189 mlog_errno(ret);
6190 goto out_commit;
6191 }
6192
6193 new_oi = OCFS2_I(args->new_inode);
6194 spin_lock(&new_oi->ip_lock);
6195 new_oi->ip_dyn_features |= OCFS2_HAS_XATTR_FL | OCFS2_INLINE_XATTR_FL;
6196 new_di->i_dyn_features = cpu_to_le16(new_oi->ip_dyn_features);
6197 spin_unlock(&new_oi->ip_lock);
6198
6199 ocfs2_journal_dirty(handle, args->new_bh);
6200
6201out_commit:
6202 ocfs2_commit_trans(osb, handle);
6203
6204out:
6205 if (meta_ac)
6206 ocfs2_free_alloc_context(meta_ac);
6207 return ret;
6208}
6209
6210static int ocfs2_create_empty_xattr_block(struct inode *inode,
6211 struct buffer_head *fe_bh,
6212 struct buffer_head **ret_bh,
6213 int indexed)
6214{
6215 int ret;
6216 handle_t *handle;
6217 struct ocfs2_alloc_context *meta_ac;
6218 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
6219
6220 ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac);
6221 if (ret < 0) {
6222 mlog_errno(ret);
6223 return ret;
6224 }
6225
6226 handle = ocfs2_start_trans(osb, OCFS2_XATTR_BLOCK_CREATE_CREDITS);
6227 if (IS_ERR(handle)) {
6228 ret = PTR_ERR(handle);
6229 mlog_errno(ret);
6230 goto out;
6231 }
6232
6233 mlog(0, "create new xattr block for inode %llu, index = %d\n",
6234 (unsigned long long)fe_bh->b_blocknr, indexed);
6235 ret = ocfs2_create_xattr_block(handle, inode, fe_bh,
6236 meta_ac, ret_bh, indexed);
6237 if (ret)
6238 mlog_errno(ret);
6239
6240 ocfs2_commit_trans(osb, handle);
6241out:
6242 ocfs2_free_alloc_context(meta_ac);
6243 return ret;
6244}
6245
6246static int ocfs2_reflink_xattr_block(struct ocfs2_xattr_reflink *args,
6247 struct buffer_head *blk_bh,
6248 struct buffer_head *new_blk_bh)
6249{
6250 int ret = 0, credits = 0;
6251 handle_t *handle;
6252 struct ocfs2_inode_info *new_oi = OCFS2_I(args->new_inode);
6253 struct ocfs2_dinode *new_di;
6254 struct ocfs2_super *osb = OCFS2_SB(args->new_inode->i_sb);
6255 int header_off = offsetof(struct ocfs2_xattr_block, xb_attrs.xb_header);
6256 struct ocfs2_xattr_block *xb =
6257 (struct ocfs2_xattr_block *)blk_bh->b_data;
6258 struct ocfs2_xattr_header *xh = &xb->xb_attrs.xb_header;
6259 struct ocfs2_xattr_block *new_xb =
6260 (struct ocfs2_xattr_block *)new_blk_bh->b_data;
6261 struct ocfs2_xattr_header *new_xh = &new_xb->xb_attrs.xb_header;
6262 struct ocfs2_alloc_context *meta_ac;
6263 struct ocfs2_xattr_value_buf vb = {
6264 .vb_bh = new_blk_bh,
6265 .vb_access = ocfs2_journal_access_xb,
6266 };
6267
6268 ret = ocfs2_reflink_lock_xattr_allocators(osb, xh, args->ref_root_bh,
6269 &credits, &meta_ac);
6270 if (ret) {
6271 mlog_errno(ret);
6272 return ret;
6273 }
6274
6275 /* One more credits in case we need to add xattr flags in new inode. */
6276 handle = ocfs2_start_trans(osb, credits + 1);
6277 if (IS_ERR(handle)) {
6278 ret = PTR_ERR(handle);
6279 mlog_errno(ret);
6280 goto out;
6281 }
6282
6283 if (!(new_oi->ip_dyn_features & OCFS2_HAS_XATTR_FL)) {
6284 ret = ocfs2_journal_access_di(handle,
6285 INODE_CACHE(args->new_inode),
6286 args->new_bh,
6287 OCFS2_JOURNAL_ACCESS_WRITE);
6288 if (ret) {
6289 mlog_errno(ret);
6290 goto out_commit;
6291 }
6292 }
6293
6294 ret = ocfs2_journal_access_xb(handle, INODE_CACHE(args->new_inode),
6295 new_blk_bh, OCFS2_JOURNAL_ACCESS_WRITE);
6296 if (ret) {
6297 mlog_errno(ret);
6298 goto out_commit;
6299 }
6300
6301 memcpy(new_blk_bh->b_data + header_off, blk_bh->b_data + header_off,
6302 osb->sb->s_blocksize - header_off);
6303
6304 ret = ocfs2_reflink_xattr_header(handle, args, blk_bh, xh,
6305 new_blk_bh, new_xh, &vb, meta_ac,
6306 ocfs2_get_xattr_value_root, NULL);
6307 if (ret) {
6308 mlog_errno(ret);
6309 goto out_commit;
6310 }
6311
6312 ocfs2_journal_dirty(handle, new_blk_bh);
6313
6314 if (!(new_oi->ip_dyn_features & OCFS2_HAS_XATTR_FL)) {
6315 new_di = (struct ocfs2_dinode *)args->new_bh->b_data;
6316 spin_lock(&new_oi->ip_lock);
6317 new_oi->ip_dyn_features |= OCFS2_HAS_XATTR_FL;
6318 new_di->i_dyn_features = cpu_to_le16(new_oi->ip_dyn_features);
6319 spin_unlock(&new_oi->ip_lock);
6320
6321 ocfs2_journal_dirty(handle, args->new_bh);
6322 }
6323
6324out_commit:
6325 ocfs2_commit_trans(osb, handle);
6326
6327out:
6328 ocfs2_free_alloc_context(meta_ac);
6329 return ret;
6330}
6331
6332struct ocfs2_reflink_xattr_tree_args {
6333 struct ocfs2_xattr_reflink *reflink;
6334 struct buffer_head *old_blk_bh;
6335 struct buffer_head *new_blk_bh;
6336 struct ocfs2_xattr_bucket *old_bucket;
6337 struct ocfs2_xattr_bucket *new_bucket;
6338};
6339
6340/*
6341 * NOTE:
6342 * We have to handle the case that both old bucket and new bucket
6343 * will call this function to get the right ret_bh.
6344 * So The caller must give us the right bh.
6345 */
6346static int ocfs2_get_reflink_xattr_value_root(struct super_block *sb,
6347 struct buffer_head *bh,
6348 struct ocfs2_xattr_header *xh,
6349 int offset,
6350 struct ocfs2_xattr_value_root **xv,
6351 struct buffer_head **ret_bh,
6352 void *para)
6353{
6354 struct ocfs2_reflink_xattr_tree_args *args =
6355 (struct ocfs2_reflink_xattr_tree_args *)para;
6356 struct ocfs2_xattr_bucket *bucket;
6357
6358 if (bh == args->old_bucket->bu_bhs[0])
6359 bucket = args->old_bucket;
6360 else
6361 bucket = args->new_bucket;
6362
6363 return ocfs2_get_xattr_tree_value_root(sb, bucket, offset,
6364 xv, ret_bh);
6365}
6366
6367struct ocfs2_value_tree_metas {
6368 int num_metas;
6369 int credits;
6370 int num_recs;
6371};
6372
6373static int ocfs2_value_tree_metas_in_bucket(struct super_block *sb,
6374 struct buffer_head *bh,
6375 struct ocfs2_xattr_header *xh,
6376 int offset,
6377 struct ocfs2_xattr_value_root **xv,
6378 struct buffer_head **ret_bh,
6379 void *para)
6380{
6381 struct ocfs2_xattr_bucket *bucket =
6382 (struct ocfs2_xattr_bucket *)para;
6383
6384 return ocfs2_get_xattr_tree_value_root(sb, bucket, offset,
6385 xv, ret_bh);
6386}
6387
6388static int ocfs2_calc_value_tree_metas(struct inode *inode,
6389 struct ocfs2_xattr_bucket *bucket,
6390 void *para)
6391{
6392 struct ocfs2_value_tree_metas *metas =
6393 (struct ocfs2_value_tree_metas *)para;
6394 struct ocfs2_xattr_header *xh =
6395 (struct ocfs2_xattr_header *)bucket->bu_bhs[0]->b_data;
6396
6397 /* Add the credits for this bucket first. */
6398 metas->credits += bucket->bu_blocks;
6399 return ocfs2_value_metas_in_xattr_header(inode->i_sb, bucket->bu_bhs[0],
6400 xh, &metas->num_metas,
6401 &metas->credits, &metas->num_recs,
6402 ocfs2_value_tree_metas_in_bucket,
6403 bucket);
6404}
6405
6406/*
6407 * Given a xattr extent rec starting from blkno and having len clusters,
6408 * iterate all the buckets calculate how much metadata we need for reflinking
6409 * all the ocfs2_xattr_value_root and lock the allocators accordingly.
6410 */
6411static int ocfs2_lock_reflink_xattr_rec_allocators(
6412 struct ocfs2_reflink_xattr_tree_args *args,
6413 struct ocfs2_extent_tree *xt_et,
6414 u64 blkno, u32 len, int *credits,
6415 struct ocfs2_alloc_context **meta_ac,
6416 struct ocfs2_alloc_context **data_ac)
6417{
6418 int ret, num_free_extents;
6419 struct ocfs2_value_tree_metas metas;
6420 struct ocfs2_super *osb = OCFS2_SB(args->reflink->old_inode->i_sb);
6421 struct ocfs2_refcount_block *rb;
6422
6423 memset(&metas, 0, sizeof(metas));
6424
6425 ret = ocfs2_iterate_xattr_buckets(args->reflink->old_inode, blkno, len,
6426 ocfs2_calc_value_tree_metas, &metas);
6427 if (ret) {
6428 mlog_errno(ret);
6429 goto out;
6430 }
6431
6432 *credits = metas.credits;
6433
6434 /*
6435 * Calculate we need for refcount tree change.
6436 *
6437 * We need to add/modify num_recs in refcount tree, so just calculate
6438 * an approximate number we need for refcount tree change.
6439 * Sometimes we need to split the tree, and after split, half recs
6440 * will be moved to the new block, and a new block can only provide
6441 * half number of recs. So we multiple new blocks by 2.
6442 * In the end, we have to add credits for modifying the already
6443 * existed refcount block.
6444 */
6445 rb = (struct ocfs2_refcount_block *)args->reflink->ref_root_bh->b_data;
6446 metas.num_recs =
6447 (metas.num_recs + ocfs2_refcount_recs_per_rb(osb->sb) - 1) /
6448 ocfs2_refcount_recs_per_rb(osb->sb) * 2;
6449 metas.num_metas += metas.num_recs;
6450 *credits += metas.num_recs +
6451 metas.num_recs * OCFS2_EXPAND_REFCOUNT_TREE_CREDITS;
6452 if (le32_to_cpu(rb->rf_flags) & OCFS2_REFCOUNT_TREE_FL)
6453 *credits += le16_to_cpu(rb->rf_list.l_tree_depth) *
6454 le16_to_cpu(rb->rf_list.l_next_free_rec) + 1;
6455 else
6456 *credits += 1;
6457
6458 /* count in the xattr tree change. */
6459 num_free_extents = ocfs2_num_free_extents(osb, xt_et);
6460 if (num_free_extents < 0) {
6461 ret = num_free_extents;
6462 mlog_errno(ret);
6463 goto out;
6464 }
6465
6466 if (num_free_extents < len)
6467 metas.num_metas += ocfs2_extend_meta_needed(xt_et->et_root_el);
6468
6469 *credits += ocfs2_calc_extend_credits(osb->sb,
6470 xt_et->et_root_el, len);
6471
6472 if (metas.num_metas) {
6473 ret = ocfs2_reserve_new_metadata_blocks(osb, metas.num_metas,
6474 meta_ac);
6475 if (ret) {
6476 mlog_errno(ret);
6477 goto out;
6478 }
6479 }
6480
6481 if (len) {
6482 ret = ocfs2_reserve_clusters(osb, len, data_ac);
6483 if (ret)
6484 mlog_errno(ret);
6485 }
6486out:
6487 if (ret) {
6488 if (*meta_ac) {
6489 ocfs2_free_alloc_context(*meta_ac);
6490 meta_ac = NULL;
6491 }
6492 }
6493
6494 return ret;
6495}
6496
6497static int ocfs2_reflink_xattr_buckets(handle_t *handle,
6498 u64 blkno, u64 new_blkno, u32 clusters,
6499 struct ocfs2_alloc_context *meta_ac,
6500 struct ocfs2_alloc_context *data_ac,
6501 struct ocfs2_reflink_xattr_tree_args *args)
6502{
6503 int i, j, ret = 0;
6504 struct super_block *sb = args->reflink->old_inode->i_sb;
6505 u32 bpc = ocfs2_xattr_buckets_per_cluster(OCFS2_SB(sb));
6506 u32 num_buckets = clusters * bpc;
6507 int bpb = args->old_bucket->bu_blocks;
6508 struct ocfs2_xattr_value_buf vb = {
6509 .vb_access = ocfs2_journal_access,
6510 };
6511
6512 for (i = 0; i < num_buckets; i++, blkno += bpb, new_blkno += bpb) {
6513 ret = ocfs2_read_xattr_bucket(args->old_bucket, blkno);
6514 if (ret) {
6515 mlog_errno(ret);
6516 break;
6517 }
6518
6519 ret = ocfs2_init_xattr_bucket(args->new_bucket, new_blkno);
6520 if (ret) {
6521 mlog_errno(ret);
6522 break;
6523 }
6524
6525 /*
6526 * The real bucket num in this series of blocks is stored
6527 * in the 1st bucket.
6528 */
6529 if (i == 0)
6530 num_buckets = le16_to_cpu(
6531 bucket_xh(args->old_bucket)->xh_num_buckets);
6532
6533 ret = ocfs2_xattr_bucket_journal_access(handle,
6534 args->new_bucket,
6535 OCFS2_JOURNAL_ACCESS_CREATE);
6536 if (ret) {
6537 mlog_errno(ret);
6538 break;
6539 }
6540
6541 for (j = 0; j < bpb; j++)
6542 memcpy(bucket_block(args->new_bucket, j),
6543 bucket_block(args->old_bucket, j),
6544 sb->s_blocksize);
6545
6546 ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket);
6547
6548 ret = ocfs2_reflink_xattr_header(handle, args->reflink,
6549 args->old_bucket->bu_bhs[0],
6550 bucket_xh(args->old_bucket),
6551 args->new_bucket->bu_bhs[0],
6552 bucket_xh(args->new_bucket),
6553 &vb, meta_ac,
6554 ocfs2_get_reflink_xattr_value_root,
6555 args);
6556 if (ret) {
6557 mlog_errno(ret);
6558 break;
6559 }
6560
6561 /*
6562 * Re-access and dirty the bucket to calculate metaecc.
6563 * Because we may extend the transaction in reflink_xattr_header
6564 * which will let the already accessed block gone.
6565 */
6566 ret = ocfs2_xattr_bucket_journal_access(handle,
6567 args->new_bucket,
6568 OCFS2_JOURNAL_ACCESS_WRITE);
6569 if (ret) {
6570 mlog_errno(ret);
6571 break;
6572 }
6573
6574 ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket);
6575 ocfs2_xattr_bucket_relse(args->old_bucket);
6576 ocfs2_xattr_bucket_relse(args->new_bucket);
6577 }
6578
6579 ocfs2_xattr_bucket_relse(args->old_bucket);
6580 ocfs2_xattr_bucket_relse(args->new_bucket);
6581 return ret;
6582}
6583/*
6584 * Create the same xattr extent record in the new inode's xattr tree.
6585 */
6586static int ocfs2_reflink_xattr_rec(struct inode *inode,
6587 struct buffer_head *root_bh,
6588 u64 blkno,
6589 u32 cpos,
6590 u32 len,
6591 void *para)
6592{
6593 int ret, credits = 0;
6594 u32 p_cluster, num_clusters;
6595 u64 new_blkno;
6596 handle_t *handle;
6597 struct ocfs2_reflink_xattr_tree_args *args =
6598 (struct ocfs2_reflink_xattr_tree_args *)para;
6599 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
6600 struct ocfs2_alloc_context *meta_ac = NULL;
6601 struct ocfs2_alloc_context *data_ac = NULL;
6602 struct ocfs2_extent_tree et;
6603
6604 ocfs2_init_xattr_tree_extent_tree(&et,
6605 INODE_CACHE(args->reflink->new_inode),
6606 args->new_blk_bh);
6607
6608 ret = ocfs2_lock_reflink_xattr_rec_allocators(args, &et, blkno,
6609 len, &credits,
6610 &meta_ac, &data_ac);
6611 if (ret) {
6612 mlog_errno(ret);
6613 goto out;
6614 }
6615
6616 handle = ocfs2_start_trans(osb, credits);
6617 if (IS_ERR(handle)) {
6618 ret = PTR_ERR(handle);
6619 mlog_errno(ret);
6620 goto out;
6621 }
6622
6623 ret = ocfs2_claim_clusters(osb, handle, data_ac,
6624 len, &p_cluster, &num_clusters);
6625 if (ret) {
6626 mlog_errno(ret);
6627 goto out_commit;
6628 }
6629
6630 new_blkno = ocfs2_clusters_to_blocks(osb->sb, p_cluster);
6631
6632 mlog(0, "reflink xattr buckets %llu to %llu, len %u\n",
6633 (unsigned long long)blkno, (unsigned long long)new_blkno, len);
6634 ret = ocfs2_reflink_xattr_buckets(handle, blkno, new_blkno, len,
6635 meta_ac, data_ac, args);
6636 if (ret) {
6637 mlog_errno(ret);
6638 goto out_commit;
6639 }
6640
6641 mlog(0, "insert new xattr extent rec start %llu len %u to %u\n",
6642 (unsigned long long)new_blkno, len, cpos);
6643 ret = ocfs2_insert_extent(handle, &et, cpos, new_blkno,
6644 len, 0, meta_ac);
6645 if (ret)
6646 mlog_errno(ret);
6647
6648out_commit:
6649 ocfs2_commit_trans(osb, handle);
6650
6651out:
6652 if (meta_ac)
6653 ocfs2_free_alloc_context(meta_ac);
6654 if (data_ac)
6655 ocfs2_free_alloc_context(data_ac);
6656 return ret;
6657}
6658
6659/*
6660 * Create reflinked xattr buckets.
6661 * We will add bucket one by one, and refcount all the xattrs in the bucket
6662 * if they are stored outside.
6663 */
6664static int ocfs2_reflink_xattr_tree(struct ocfs2_xattr_reflink *args,
6665 struct buffer_head *blk_bh,
6666 struct buffer_head *new_blk_bh)
6667{
6668 int ret;
6669 struct ocfs2_reflink_xattr_tree_args para;
6670
6671 memset(&para, 0, sizeof(para));
6672 para.reflink = args;
6673 para.old_blk_bh = blk_bh;
6674 para.new_blk_bh = new_blk_bh;
6675
6676 para.old_bucket = ocfs2_xattr_bucket_new(args->old_inode);
6677 if (!para.old_bucket) {
6678 mlog_errno(-ENOMEM);
6679 return -ENOMEM;
6680 }
6681
6682 para.new_bucket = ocfs2_xattr_bucket_new(args->new_inode);
6683 if (!para.new_bucket) {
6684 ret = -ENOMEM;
6685 mlog_errno(ret);
6686 goto out;
6687 }
6688
6689 ret = ocfs2_iterate_xattr_index_block(args->old_inode, blk_bh,
6690 ocfs2_reflink_xattr_rec,
6691 &para);
6692 if (ret)
6693 mlog_errno(ret);
6694
6695out:
6696 ocfs2_xattr_bucket_free(para.old_bucket);
6697 ocfs2_xattr_bucket_free(para.new_bucket);
6698 return ret;
6699}
6700
6701static int ocfs2_reflink_xattr_in_block(struct ocfs2_xattr_reflink *args,
6702 struct buffer_head *blk_bh)
6703{
6704 int ret, indexed = 0;
6705 struct buffer_head *new_blk_bh = NULL;
6706 struct ocfs2_xattr_block *xb =
6707 (struct ocfs2_xattr_block *)blk_bh->b_data;
6708
6709
6710 if (le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)
6711 indexed = 1;
6712
6713 ret = ocfs2_create_empty_xattr_block(args->new_inode, args->new_bh,
6714 &new_blk_bh, indexed);
6715 if (ret) {
6716 mlog_errno(ret);
6717 goto out;
6718 }
6719
6720 if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED))
6721 ret = ocfs2_reflink_xattr_block(args, blk_bh, new_blk_bh);
6722 else
6723 ret = ocfs2_reflink_xattr_tree(args, blk_bh, new_blk_bh);
6724 if (ret)
6725 mlog_errno(ret);
6726
6727out:
6728 brelse(new_blk_bh);
6729 return ret;
6730}
6731
6732int ocfs2_reflink_xattrs(struct inode *old_inode,
6733 struct buffer_head *old_bh,
6734 struct inode *new_inode,
6735 struct buffer_head *new_bh)
6736{
6737 int ret;
6738 struct ocfs2_xattr_reflink args;
6739 struct ocfs2_inode_info *oi = OCFS2_I(old_inode);
6740 struct ocfs2_dinode *di = (struct ocfs2_dinode *)old_bh->b_data;
6741 struct buffer_head *blk_bh = NULL;
6742 struct ocfs2_cached_dealloc_ctxt dealloc;
6743 struct ocfs2_refcount_tree *ref_tree;
6744 struct buffer_head *ref_root_bh = NULL;
6745
6746 ret = ocfs2_lock_refcount_tree(OCFS2_SB(old_inode->i_sb),
6747 le64_to_cpu(di->i_refcount_loc),
6748 1, &ref_tree, &ref_root_bh);
6749 if (ret) {
6750 mlog_errno(ret);
6751 goto out;
6752 }
6753
6754 ocfs2_init_dealloc_ctxt(&dealloc);
6755
6756 args.old_inode = old_inode;
6757 args.new_inode = new_inode;
6758 args.old_bh = old_bh;
6759 args.new_bh = new_bh;
6760 args.ref_ci = &ref_tree->rf_ci;
6761 args.ref_root_bh = ref_root_bh;
6762 args.dealloc = &dealloc;
6763
6764 if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) {
6765 ret = ocfs2_reflink_xattr_inline(&args);
6766 if (ret) {
6767 mlog_errno(ret);
6768 goto out_unlock;
6769 }
6770 }
6771
6772 if (!di->i_xattr_loc)
6773 goto out_unlock;
6774
6775 ret = ocfs2_read_xattr_block(old_inode, le64_to_cpu(di->i_xattr_loc),
6776 &blk_bh);
6777 if (ret < 0) {
6778 mlog_errno(ret);
6779 goto out_unlock;
6780 }
6781
6782 ret = ocfs2_reflink_xattr_in_block(&args, blk_bh);
6783 if (ret)
6784 mlog_errno(ret);
6785
6786 brelse(blk_bh);
6787
6788out_unlock:
6789 ocfs2_unlock_refcount_tree(OCFS2_SB(old_inode->i_sb),
6790 ref_tree, 1);
6791 brelse(ref_root_bh);
6792
6793 if (ocfs2_dealloc_has_cluster(&dealloc)) {
6794 ocfs2_schedule_truncate_log_flush(OCFS2_SB(old_inode->i_sb), 1);
6795 ocfs2_run_deallocs(OCFS2_SB(old_inode->i_sb), &dealloc);
6796 }
6797
6798out:
6799 return ret;
6800}
6801
6802/*
5880 * 'security' attributes support 6803 * 'security' attributes support
5881 */ 6804 */
5882static size_t ocfs2_xattr_security_list(struct inode *inode, char *list, 6805static size_t ocfs2_xattr_security_list(struct inode *inode, char *list,
diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h
index e74703f56dca..4f913053d5ee 100644
--- a/fs/ocfs2/xattr.h
+++ b/fs/ocfs2/xattr.h
@@ -90,4 +90,8 @@ int ocfs2_xattr_attach_refcount_tree(struct inode *inode,
90 struct ocfs2_caching_info *ref_ci, 90 struct ocfs2_caching_info *ref_ci,
91 struct buffer_head *ref_root_bh, 91 struct buffer_head *ref_root_bh,
92 struct ocfs2_cached_dealloc_ctxt *dealloc); 92 struct ocfs2_cached_dealloc_ctxt *dealloc);
93int ocfs2_reflink_xattrs(struct inode *old_inode,
94 struct buffer_head *old_bh,
95 struct inode *new_inode,
96 struct buffer_head *new_bh);
93#endif /* OCFS2_XATTR_H */ 97#endif /* OCFS2_XATTR_H */