Commit 15d60929 authored by Joel Becker's avatar Joel Becker Committed by Mark Fasheh

ocfs2: Dirty the entire first bucket in ocfs2_cp_xattr_cluster().

ocfs2_cp_xattr_cluster() takes the last bucket of a full extent and
copies it over to a new extent.  It then updates the headers of both
extents to reflect the new state.  It is passed the first bh of
the first bucket in order to update that first extent's bucket count.
It reads and dirties the first bh of the new extent for the same reason.

However, future code wants to always dirty the entire bucket when it
is changed.  So it is changed to read the entire bucket it is updating
for both extents.
Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
parent 92de109a
...@@ -3936,9 +3936,10 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode, ...@@ -3936,9 +3936,10 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode,
} }
/* /*
* Copy one xattr cluster from src_blk to to_blk. * src_blk points to the last cluster of an existing extent. to_blk
* The to_blk will become the first bucket header of the cluster, so its * points to a newly allocated extent. We copy the cluster over to the
* xh_num_buckets will be initialized as the bucket num in the cluster. * new extent, initializing its xh_num_buckets. The old extent's
* xh_num_buckets shrinks by the same amount.
*/ */
static int ocfs2_cp_xattr_cluster(struct inode *inode, static int ocfs2_cp_xattr_cluster(struct inode *inode,
handle_t *handle, handle_t *handle,
...@@ -3950,27 +3951,42 @@ static int ocfs2_cp_xattr_cluster(struct inode *inode, ...@@ -3950,27 +3951,42 @@ static int ocfs2_cp_xattr_cluster(struct inode *inode,
int i, ret, credits; int i, ret, credits;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
int blks_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
int num_buckets = ocfs2_xattr_buckets_per_cluster(osb); int num_buckets = ocfs2_xattr_buckets_per_cluster(osb);
struct buffer_head *bh = NULL; struct ocfs2_xattr_bucket *old_first, *new_first;
struct ocfs2_xattr_header *xh;
u64 to_blk_start = to_blk;
mlog(0, "cp xattrs from cluster %llu to %llu\n", mlog(0, "cp xattrs from cluster %llu to %llu\n",
(unsigned long long)src_blk, (unsigned long long)to_blk); (unsigned long long)src_blk, (unsigned long long)to_blk);
/* The first bucket of the original extent */
old_first = ocfs2_xattr_bucket_new(inode);
/* The first bucket of the new extent */
new_first = ocfs2_xattr_bucket_new(inode);
if (!old_first || !new_first) {
ret = -ENOMEM;
mlog_errno(ret);
goto out;
}
ret = ocfs2_read_xattr_bucket(old_first, first_bh->b_blocknr);
if (ret) {
mlog_errno(ret);
goto out;
}
/* /*
* We need to update the new cluster and 1 more for the update of * We need to update the first bucket of the old extent and the
* the 1st bucket of the previous extent rec. * entire first cluster of the new extent.
*/ */
credits = bpc + 1 + handle->h_buffer_credits; credits = blks_per_bucket + bpc + handle->h_buffer_credits;
ret = ocfs2_extend_trans(handle, credits); ret = ocfs2_extend_trans(handle, credits);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
} }
ret = ocfs2_journal_access(handle, inode, first_bh, ret = ocfs2_xattr_bucket_journal_access(handle, old_first,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
...@@ -3978,45 +3994,45 @@ static int ocfs2_cp_xattr_cluster(struct inode *inode, ...@@ -3978,45 +3994,45 @@ static int ocfs2_cp_xattr_cluster(struct inode *inode,
for (i = 0; i < num_buckets; i++) { for (i = 0; i < num_buckets; i++) {
ret = ocfs2_cp_xattr_bucket(inode, handle, ret = ocfs2_cp_xattr_bucket(inode, handle,
src_blk, to_blk, 1); src_blk + (i * blks_per_bucket),
to_blk + (i * blks_per_bucket),
1);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
} }
src_blk += ocfs2_blocks_per_xattr_bucket(inode->i_sb);
to_blk += ocfs2_blocks_per_xattr_bucket(inode->i_sb);
} }
/* update the old bucket header. */ /*
xh = (struct ocfs2_xattr_header *)first_bh->b_data; * Get the new bucket ready before we dirty anything
le16_add_cpu(&xh->xh_num_buckets, -num_buckets); * (This actually shouldn't fail, because we already dirtied
* it once in ocfs2_cp_xattr_bucket()).
ocfs2_journal_dirty(handle, first_bh); */
ret = ocfs2_read_xattr_bucket(new_first, to_blk);
/* update the new bucket header. */ if (ret) {
ret = ocfs2_read_block(inode, to_blk_start, &bh, NULL);
if (ret < 0) {
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
} }
ret = ocfs2_xattr_bucket_journal_access(handle, new_first,
ret = ocfs2_journal_access(handle, inode, bh, OCFS2_JOURNAL_ACCESS_WRITE);
OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
} }
xh = (struct ocfs2_xattr_header *)bh->b_data; /* Now update the headers */
xh->xh_num_buckets = cpu_to_le16(num_buckets); le16_add_cpu(&bucket_xh(old_first)->xh_num_buckets, -num_buckets);
ocfs2_xattr_bucket_journal_dirty(handle, old_first);
ocfs2_journal_dirty(handle, bh); bucket_xh(new_first)->xh_num_buckets = cpu_to_le16(num_buckets);
ocfs2_xattr_bucket_journal_dirty(handle, new_first);
if (first_hash) if (first_hash)
*first_hash = le32_to_cpu(xh->xh_entries[0].xe_name_hash); *first_hash = le32_to_cpu(bucket_xh(new_first)->xh_entries[0].xe_name_hash);
out: out:
brelse(bh); ocfs2_xattr_bucket_free(new_first);
ocfs2_xattr_bucket_free(old_first);
return ret; return ret;
} }
......
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