[Ocfs2-devel] [PATCH 01/13] ocfs2: Dirty the entire bucket in ocfs2_bucket_value_truncate()

Tao Ma tao.ma at oracle.com
Wed Nov 26 17:23:52 PST 2008



Joel Becker wrote:
> ocfs2_bucket_value_truncate() currently takes the first bh of the
> bucket, and magically plays around with the value bh - even though
> the bucket structure in the calling function already has it.
> 
> In addition, future code wants to always dirty the entire bucket when it
> is changed.  So let's pass the entire bucket into this function, skip
> any block reads (we have them), and add the access/dirty logic
> 
> Signed-off-by: Joel Becker <joel.becker at oracle.com>
> ---
>  fs/ocfs2/xattr.c |   44 ++++++++++++++++++++++++++------------------
>  1 files changed, 26 insertions(+), 18 deletions(-)
> 
> diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
> index 7e0d62a..4571df8 100644
> --- a/fs/ocfs2/xattr.c
> +++ b/fs/ocfs2/xattr.c
> @@ -4619,7 +4619,7 @@ out:
>   * Copy the new updated xe and xe_value_root to new_xe and new_xv if needed.
>   */
>  static int ocfs2_xattr_bucket_value_truncate(struct inode *inode,
> -					     struct buffer_head *header_bh,
> +					     struct ocfs2_xattr_bucket *bucket,
>  					     int xe_off,
>  					     int len,
>  					     struct ocfs2_xattr_set_ctxt *ctxt)
> @@ -4629,8 +4629,7 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode,
>  	struct buffer_head *value_bh = NULL;
>  	struct ocfs2_xattr_value_root *xv;
>  	struct ocfs2_xattr_entry *xe;
> -	struct ocfs2_xattr_header *xh =
> -			(struct ocfs2_xattr_header *)header_bh->b_data;
> +	struct ocfs2_xattr_header *xh = bucket_xh(bucket);
>  	size_t blocksize = inode->i_sb->s_blocksize;
>  
>  	xe = &xh->xh_entries[xe_off];
> @@ -4644,34 +4643,44 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode,
>  
>  	/* We don't allow ocfs2_xattr_value to be stored in different block. */
>  	BUG_ON(value_blk != (offset + OCFS2_XATTR_ROOT_SIZE - 1) / blocksize);
> -	value_blk += header_bh->b_blocknr;
>  
> -	ret = ocfs2_read_block(inode, value_blk, &value_bh, NULL);
> +	value_bh = bucket->bu_bhs[value_blk];
> +	BUG_ON(!value_bh);
> +
> +	xv = (struct ocfs2_xattr_value_root *)
> +		(value_bh->b_data + offset % blocksize);
> +
> +	ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket,
> +						OCFS2_JOURNAL_ACCESS_WRITE);
>  	if (ret) {
>  		mlog_errno(ret);
>  		goto out;
>  	}
>  
> -	xv = (struct ocfs2_xattr_value_root *)
> -		(value_bh->b_data + offset % blocksize);
> -
> +	/*
> +	 * From here on out we have to dirty the bucket.  The generic
> +	 * value calls only modify one of the bucket's bhs, but we need
> +	 * to send the bucket at once.  So if they error, they *could* have
> +	 * modified something.  We have to assume they did, and dirty
> +	 * the whole bucket.  This leaves us in a consistent state.
> +	 */
>  	mlog(0, "truncate %u in xattr bucket %llu to %d bytes.\n",
> -	     xe_off, (unsigned long long)header_bh->b_blocknr, len);
> +	     xe_off, (unsigned long long)bucket_blkno(bucket), len);
>  	ret = ocfs2_xattr_value_truncate(inode, value_bh, xv, len, ctxt);
>  	if (ret) {
>  		mlog_errno(ret);
> -		goto out;
> +		goto out_dirty;
>  	}
>  
>  	ret = ocfs2_xattr_value_update_size(inode, ctxt->handle,
> -					    header_bh, xe, len);
> -	if (ret) {
> +					    bucket->bu_bhs[0], xe, len);
> +	if (ret)
ocfs2_xattr_value_update_size only access the first_bh, update the size 
and then dirty it. Since you now access and dirty the whole bucket, I 
think maybe you can just remove this function and move the size update here.
>  		mlog_errno(ret);
> -		goto out;
> -	}
> +
> +out_dirty:
> +	ocfs2_xattr_bucket_journal_dirty(ctxt->handle, bucket);
>  
>  out:
> -	brelse(value_bh);
>  	return ret;
>  }

Regards,
Tao



More information about the Ocfs2-devel mailing list