Commit 121a39bb authored by Tao Ma's avatar Tao Ma Committed by Joel Becker

ocfs2: Make xattr reflink work with new local alloc reservation.

The new reservation code in local alloc has add the limitation
that the caller should handle the case that the local alloc
doesn't give use enough contiguous clusters. It make the old
xattr reflink code broken.

So this patch udpate the xattr reflink code so that it can
handle the case that local alloc give us one cluster at a time.
Signed-off-by: default avatarTao Ma <tao.ma@oracle.com>
Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
parent a78f9f46
...@@ -6804,16 +6804,15 @@ static int ocfs2_lock_reflink_xattr_rec_allocators( ...@@ -6804,16 +6804,15 @@ static int ocfs2_lock_reflink_xattr_rec_allocators(
return ret; return ret;
} }
static int ocfs2_reflink_xattr_buckets(handle_t *handle, static int ocfs2_reflink_xattr_bucket(handle_t *handle,
u64 blkno, u64 new_blkno, u32 clusters, u64 blkno, u64 new_blkno, u32 clusters,
u32 *cpos, int num_buckets,
struct ocfs2_alloc_context *meta_ac, struct ocfs2_alloc_context *meta_ac,
struct ocfs2_alloc_context *data_ac, struct ocfs2_alloc_context *data_ac,
struct ocfs2_reflink_xattr_tree_args *args) struct ocfs2_reflink_xattr_tree_args *args)
{ {
int i, j, ret = 0; int i, j, ret = 0;
struct super_block *sb = args->reflink->old_inode->i_sb; struct super_block *sb = args->reflink->old_inode->i_sb;
u32 bpc = ocfs2_xattr_buckets_per_cluster(OCFS2_SB(sb));
u32 num_buckets = clusters * bpc;
int bpb = args->old_bucket->bu_blocks; int bpb = args->old_bucket->bu_blocks;
struct ocfs2_xattr_value_buf vb = { struct ocfs2_xattr_value_buf vb = {
.vb_access = ocfs2_journal_access, .vb_access = ocfs2_journal_access,
...@@ -6832,14 +6831,6 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, ...@@ -6832,14 +6831,6 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle,
break; break;
} }
/*
* The real bucket num in this series of blocks is stored
* in the 1st bucket.
*/
if (i == 0)
num_buckets = le16_to_cpu(
bucket_xh(args->old_bucket)->xh_num_buckets);
ret = ocfs2_xattr_bucket_journal_access(handle, ret = ocfs2_xattr_bucket_journal_access(handle,
args->new_bucket, args->new_bucket,
OCFS2_JOURNAL_ACCESS_CREATE); OCFS2_JOURNAL_ACCESS_CREATE);
...@@ -6853,6 +6844,18 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, ...@@ -6853,6 +6844,18 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle,
bucket_block(args->old_bucket, j), bucket_block(args->old_bucket, j),
sb->s_blocksize); sb->s_blocksize);
/*
* Record the start cpos so that we can use it to initialize
* our xattr tree we also set the xh_num_bucket for the new
* bucket.
*/
if (i == 0) {
*cpos = le32_to_cpu(bucket_xh(args->new_bucket)->
xh_entries[0].xe_name_hash);
bucket_xh(args->new_bucket)->xh_num_buckets =
cpu_to_le16(num_buckets);
}
ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket); ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket);
ret = ocfs2_reflink_xattr_header(handle, args->reflink, ret = ocfs2_reflink_xattr_header(handle, args->reflink,
...@@ -6882,6 +6885,7 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, ...@@ -6882,6 +6885,7 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle,
} }
ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket); ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket);
ocfs2_xattr_bucket_relse(args->old_bucket); ocfs2_xattr_bucket_relse(args->old_bucket);
ocfs2_xattr_bucket_relse(args->new_bucket); ocfs2_xattr_bucket_relse(args->new_bucket);
} }
...@@ -6890,6 +6894,75 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, ...@@ -6890,6 +6894,75 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle,
ocfs2_xattr_bucket_relse(args->new_bucket); ocfs2_xattr_bucket_relse(args->new_bucket);
return ret; return ret;
} }
static int ocfs2_reflink_xattr_buckets(handle_t *handle,
struct inode *inode,
struct ocfs2_reflink_xattr_tree_args *args,
struct ocfs2_extent_tree *et,
struct ocfs2_alloc_context *meta_ac,
struct ocfs2_alloc_context *data_ac,
u64 blkno, u32 cpos, u32 len)
{
int ret, first_inserted = 0;
u32 p_cluster, num_clusters, reflink_cpos = 0;
u64 new_blkno;
unsigned int num_buckets, reflink_buckets;
unsigned int bpc =
ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb));
ret = ocfs2_read_xattr_bucket(args->old_bucket, blkno);
if (ret) {
mlog_errno(ret);
goto out;
}
num_buckets = le16_to_cpu(bucket_xh(args->old_bucket)->xh_num_buckets);
ocfs2_xattr_bucket_relse(args->old_bucket);
while (len && num_buckets) {
ret = ocfs2_claim_clusters(handle, data_ac,
1, &p_cluster, &num_clusters);
if (ret) {
mlog_errno(ret);
goto out;
}
new_blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster);
reflink_buckets = min(num_buckets, bpc * num_clusters);
ret = ocfs2_reflink_xattr_bucket(handle, blkno,
new_blkno, num_clusters,
&reflink_cpos, reflink_buckets,
meta_ac, data_ac, args);
if (ret) {
mlog_errno(ret);
goto out;
}
/*
* For the 1st allocated cluster, we make it use the same cpos
* so that the xattr tree looks the same as the original one
* in the most case.
*/
if (!first_inserted) {
reflink_cpos = cpos;
first_inserted = 1;
}
ret = ocfs2_insert_extent(handle, et, reflink_cpos, new_blkno,
num_clusters, 0, meta_ac);
if (ret)
mlog_errno(ret);
mlog(0, "insert new xattr extent rec start %llu len %u to %u\n",
(unsigned long long)new_blkno, num_clusters, reflink_cpos);
len -= num_clusters;
blkno += ocfs2_clusters_to_blocks(inode->i_sb, num_clusters);
num_buckets -= reflink_buckets;
}
out:
return ret;
}
/* /*
* Create the same xattr extent record in the new inode's xattr tree. * Create the same xattr extent record in the new inode's xattr tree.
*/ */
...@@ -6901,8 +6974,6 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode, ...@@ -6901,8 +6974,6 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode,
void *para) void *para)
{ {
int ret, credits = 0; int ret, credits = 0;
u32 p_cluster, num_clusters;
u64 new_blkno;
handle_t *handle; handle_t *handle;
struct ocfs2_reflink_xattr_tree_args *args = struct ocfs2_reflink_xattr_tree_args *args =
(struct ocfs2_reflink_xattr_tree_args *)para; (struct ocfs2_reflink_xattr_tree_args *)para;
...@@ -6911,6 +6982,9 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode, ...@@ -6911,6 +6982,9 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode,
struct ocfs2_alloc_context *data_ac = NULL; struct ocfs2_alloc_context *data_ac = NULL;
struct ocfs2_extent_tree et; struct ocfs2_extent_tree et;
mlog(0, "reflink xattr buckets %llu len %u\n",
(unsigned long long)blkno, len);
ocfs2_init_xattr_tree_extent_tree(&et, ocfs2_init_xattr_tree_extent_tree(&et,
INODE_CACHE(args->reflink->new_inode), INODE_CACHE(args->reflink->new_inode),
args->new_blk_bh); args->new_blk_bh);
...@@ -6930,32 +7004,12 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode, ...@@ -6930,32 +7004,12 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode,
goto out; goto out;
} }
ret = ocfs2_claim_clusters(handle, data_ac, ret = ocfs2_reflink_xattr_buckets(handle, inode, args, &et,
len, &p_cluster, &num_clusters); meta_ac, data_ac,
if (ret) { blkno, cpos, len);
mlog_errno(ret);
goto out_commit;
}
new_blkno = ocfs2_clusters_to_blocks(osb->sb, p_cluster);
mlog(0, "reflink xattr buckets %llu to %llu, len %u\n",
(unsigned long long)blkno, (unsigned long long)new_blkno, len);
ret = ocfs2_reflink_xattr_buckets(handle, blkno, new_blkno, len,
meta_ac, data_ac, args);
if (ret) {
mlog_errno(ret);
goto out_commit;
}
mlog(0, "insert new xattr extent rec start %llu len %u to %u\n",
(unsigned long long)new_blkno, len, cpos);
ret = ocfs2_insert_extent(handle, &et, cpos, new_blkno,
len, 0, meta_ac);
if (ret) if (ret)
mlog_errno(ret); mlog_errno(ret);
out_commit:
ocfs2_commit_trans(osb, handle); ocfs2_commit_trans(osb, handle);
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment