aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/xattr.c169
1 files changed, 104 insertions, 65 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 5efcf4e85d7c..5be99666f02c 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -170,6 +170,11 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
170 170
171static int ocfs2_delete_xattr_index_block(struct inode *inode, 171static int ocfs2_delete_xattr_index_block(struct inode *inode,
172 struct buffer_head *xb_bh); 172 struct buffer_head *xb_bh);
173static int ocfs2_cp_xattr_bucket(struct inode *inode,
174 handle_t *handle,
175 u64 s_blkno,
176 u64 t_blkno,
177 int t_is_new);
173 178
174static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb) 179static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb)
175{ 180{
@@ -3526,13 +3531,21 @@ out:
3526} 3531}
3527 3532
3528/* 3533/*
3529 * Move half nums of the xattr bucket in the previous cluster to this new 3534 * prev_blkno points to the start of an existing extent. new_blkno
3530 * cluster. We only touch the last cluster of the previous extend record. 3535 * points to a newly allocated extent. Because we know each of our
3536 * clusters contains more than bucket, we can easily split one cluster
3537 * at a bucket boundary. So we take the last cluster of the existing
3538 * extent and split it down the middle. We move the last half of the
3539 * buckets in the last cluster of the existing extent over to the new
3540 * extent.
3541 *
3542 * first_bh is the buffer at prev_blkno so we can update the existing
3543 * extent's bucket count. header_bh is the bucket were we were hoping
3544 * to insert our xattr. If the bucket move places the target in the new
3545 * extent, we'll update first_bh and header_bh after modifying the old
3546 * extent.
3531 * 3547 *
3532 * first_bh is the first buffer_head of a series of bucket in the same 3548 * first_hash will be set as the 1st xe's name_hash in the new extent.
3533 * extent rec and header_bh is the header of one bucket in this cluster.
3534 * They will be updated if we move the data header_bh contains to the new
3535 * cluster. first_hash will be set as the 1st xe's name_hash of the new cluster.
3536 */ 3549 */
3537static int ocfs2_mv_xattr_bucket_cross_cluster(struct inode *inode, 3550static int ocfs2_mv_xattr_bucket_cross_cluster(struct inode *inode,
3538 handle_t *handle, 3551 handle_t *handle,
@@ -3545,105 +3558,131 @@ static int ocfs2_mv_xattr_bucket_cross_cluster(struct inode *inode,
3545{ 3558{
3546 int i, ret, credits; 3559 int i, ret, credits;
3547 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 3560 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
3561 int blks_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
3548 int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); 3562 int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
3549 int num_buckets = ocfs2_xattr_buckets_per_cluster(osb); 3563 int num_buckets = ocfs2_xattr_buckets_per_cluster(osb);
3550 int blocksize = inode->i_sb->s_blocksize; 3564 int to_move = num_buckets / 2;
3551 struct buffer_head *old_bh, *new_bh, *prev_bh, *new_first_bh = NULL; 3565 u64 last_cluster_blkno, src_blkno;
3552 struct ocfs2_xattr_header *new_xh;
3553 struct ocfs2_xattr_header *xh = 3566 struct ocfs2_xattr_header *xh =
3554 (struct ocfs2_xattr_header *)((*first_bh)->b_data); 3567 (struct ocfs2_xattr_header *)((*first_bh)->b_data);
3568 struct ocfs2_xattr_bucket *old_first, *new_first;
3555 3569
3556 BUG_ON(le16_to_cpu(xh->xh_num_buckets) < num_buckets); 3570 BUG_ON(le16_to_cpu(xh->xh_num_buckets) < num_buckets);
3557 BUG_ON(OCFS2_XATTR_BUCKET_SIZE == osb->s_clustersize); 3571 BUG_ON(OCFS2_XATTR_BUCKET_SIZE == osb->s_clustersize);
3558 3572
3559 prev_bh = *first_bh; 3573 last_cluster_blkno = prev_blkno + ((num_clusters - 1) * bpc);
3560 get_bh(prev_bh); 3574 src_blkno = last_cluster_blkno + (to_move * blks_per_bucket);
3561 xh = (struct ocfs2_xattr_header *)prev_bh->b_data;
3562
3563 prev_blkno += (num_clusters - 1) * bpc + bpc / 2;
3564 3575
3565 mlog(0, "move half of xattrs in cluster %llu to %llu\n", 3576 mlog(0, "move half of xattrs in cluster %llu to %llu\n",
3566 (unsigned long long)prev_blkno, (unsigned long long)new_blkno); 3577 (unsigned long long)prev_blkno, (unsigned long long)new_blkno);
3567 3578
3579 /* The first bucket of the original extent */
3580 old_first = ocfs2_xattr_bucket_new(inode);
3581 /* The first bucket of the new extent */
3582 new_first = ocfs2_xattr_bucket_new(inode);
3583 if (!old_first || !new_first) {
3584 ret = -ENOMEM;
3585 mlog_errno(ret);
3586 goto out;
3587 }
3588
3589 ret = ocfs2_read_xattr_bucket(old_first, prev_blkno);
3590 if (ret) {
3591 mlog_errno(ret);
3592 goto out;
3593 }
3594
3568 /* 3595 /*
3569 * We need to update the 1st half of the new cluster and 3596 * We need to update the 1st half of the new extent, and we
3570 * 1 more for the update of the 1st bucket of the previous 3597 * need to update the first bucket of the old extent.
3571 * extent record.
3572 */ 3598 */
3573 credits = bpc / 2 + 1 + handle->h_buffer_credits; 3599 credits = ((to_move + 1) * blks_per_bucket) + handle->h_buffer_credits;
3574 ret = ocfs2_extend_trans(handle, credits); 3600 ret = ocfs2_extend_trans(handle, credits);
3575 if (ret) { 3601 if (ret) {
3576 mlog_errno(ret); 3602 mlog_errno(ret);
3577 goto out; 3603 goto out;
3578 } 3604 }
3579 3605
3580 ret = ocfs2_journal_access(handle, inode, prev_bh, 3606 ret = ocfs2_xattr_bucket_journal_access(handle, old_first,
3581 OCFS2_JOURNAL_ACCESS_WRITE); 3607 OCFS2_JOURNAL_ACCESS_WRITE);
3582 if (ret) { 3608 if (ret) {
3583 mlog_errno(ret); 3609 mlog_errno(ret);
3584 goto out; 3610 goto out;
3585 } 3611 }
3586 3612
3587 for (i = 0; i < bpc / 2; i++, prev_blkno++, new_blkno++) { 3613 for (i = 0; i < to_move; i++) {
3588 old_bh = new_bh = NULL; 3614 ret = ocfs2_cp_xattr_bucket(inode, handle,
3589 new_bh = sb_getblk(inode->i_sb, new_blkno); 3615 src_blkno + (i * blks_per_bucket),
3590 if (!new_bh) { 3616 new_blkno + (i * blks_per_bucket),
3591 ret = -EIO; 3617 1);
3618 if (ret) {
3592 mlog_errno(ret); 3619 mlog_errno(ret);
3593 goto out; 3620 goto out;
3594 } 3621 }
3622 }
3595 3623
3596 ocfs2_set_new_buffer_uptodate(inode, new_bh); 3624 /*
3625 * Get the new bucket ready before we dirty anything
3626 * (This actually shouldn't fail, because we already dirtied
3627 * it once in ocfs2_cp_xattr_bucket()).
3628 */
3629 ret = ocfs2_read_xattr_bucket(new_first, new_blkno);
3630 if (ret) {
3631 mlog_errno(ret);
3632 goto out;
3633 }
3634 ret = ocfs2_xattr_bucket_journal_access(handle, new_first,
3635 OCFS2_JOURNAL_ACCESS_WRITE);
3636 if (ret) {
3637 mlog_errno(ret);
3638 goto out;
3639 }
3597 3640
3598 ret = ocfs2_journal_access(handle, inode, new_bh, 3641 /* Now update the headers */
3599 OCFS2_JOURNAL_ACCESS_CREATE); 3642 le16_add_cpu(&bucket_xh(old_first)->xh_num_buckets, -to_move);
3600 if (ret < 0) { 3643 ocfs2_xattr_bucket_journal_dirty(handle, old_first);
3601 mlog_errno(ret);
3602 brelse(new_bh);
3603 goto out;
3604 }
3605 3644
3606 ret = ocfs2_read_block(inode, prev_blkno, &old_bh, NULL); 3645 bucket_xh(new_first)->xh_num_buckets = cpu_to_le16(to_move);
3607 if (ret < 0) { 3646 ocfs2_xattr_bucket_journal_dirty(handle, new_first);
3608 mlog_errno(ret);
3609 brelse(new_bh);
3610 goto out;
3611 }
3612 3647
3613 memcpy(new_bh->b_data, old_bh->b_data, blocksize); 3648 if (first_hash)
3649 *first_hash = le32_to_cpu(bucket_xh(new_first)->xh_entries[0].xe_name_hash);
3614 3650
3615 if (i == 0) { 3651 /*
3616 new_xh = (struct ocfs2_xattr_header *)new_bh->b_data; 3652 * If the target bucket is anywhere past src_blkno, we moved
3617 new_xh->xh_num_buckets = cpu_to_le16(num_buckets / 2); 3653 * it to the new extent. We need to update first_bh and header_bh.
3654 */
3655 if ((*header_bh)->b_blocknr >= src_blkno) {
3656 /* We're done with old_first, so we can re-use it. */
3657 ocfs2_xattr_bucket_relse(old_first);
3618 3658
3619 if (first_hash) 3659 /* Find the block for the new target bucket */
3620 *first_hash = le32_to_cpu( 3660 src_blkno = new_blkno +
3621 new_xh->xh_entries[0].xe_name_hash); 3661 ((*header_bh)->b_blocknr - src_blkno);
3622 new_first_bh = new_bh;
3623 get_bh(new_first_bh);
3624 }
3625 3662
3626 ocfs2_journal_dirty(handle, new_bh); 3663 /*
3664 * This shouldn't fail - the buffers are in the
3665 * journal from ocfs2_cp_xattr_bucket().
3666 */
3667 ret = ocfs2_read_xattr_bucket(old_first, src_blkno);
3668 if (ret) {
3669 mlog_errno(ret);
3670 goto out;
3671 }
3627 3672
3628 if (*header_bh == old_bh) { 3673 brelse(*first_bh);
3629 brelse(*header_bh); 3674 *first_bh = new_first->bu_bhs[0];
3630 *header_bh = new_bh; 3675 get_bh(*first_bh);
3631 get_bh(*header_bh);
3632 3676
3633 brelse(*first_bh); 3677 brelse(*header_bh);
3634 *first_bh = new_first_bh; 3678 *header_bh = old_first->bu_bhs[0];
3635 get_bh(*first_bh); 3679 get_bh(*header_bh);
3636 }
3637 brelse(new_bh);
3638 brelse(old_bh);
3639 } 3680 }
3640 3681
3641 le16_add_cpu(&xh->xh_num_buckets, -(num_buckets / 2));
3642
3643 ocfs2_journal_dirty(handle, prev_bh);
3644out: 3682out:
3645 brelse(prev_bh); 3683 ocfs2_xattr_bucket_free(new_first);
3646 brelse(new_first_bh); 3684 ocfs2_xattr_bucket_free(old_first);
3685
3647 return ret; 3686 return ret;
3648} 3687}
3649 3688