[Ocfs2-devel] [PATCH 10/14] ocfs2: Allocation in ocfs2_xa_prepare_entry() values in ocfs2_xa_store_value()

Tao Ma tao.ma at oracle.com
Tue Sep 1 01:55:04 PDT 2009



Joel Becker wrote:
> ocfs2_xa_prepare_entry() gets all the logic to add, remove, or modify
> external value trees.  Now, when it exits, the entry is ready to receive
> a value of any size.
> 
> ocfs2_xa_store_inline_value() becomes ocfs2_xa_store_value().  It can
> store any value.
> 
> ocfs2_xattr_set_entry() loses all the allocation logic and just uses
> these functions.  ocfs2_xattr_set_value_outside() disappears.
> 
> ocfs2_xattr_set_in_bucket() uses these functions and makes
> ocfs2_xattr_set_entry_in_bucket() obsolete.  That goes away, as does
> ocfs2_xattr_bucket_set_value_outside() and
> ocfs2_xattr_bucket_value_truncate().
> 
> Signed-off-by: Joel Becker <joel.becker at oracle.com>
> ---
>  fs/ocfs2/xattr.c |  611 ++++++++++++------------------------------------------
>  1 files changed, 138 insertions(+), 473 deletions(-)
> 
> diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
> index 1bc12fa..d922ad9 100644
> --- a/fs/ocfs2/xattr.c
> +++ b/fs/ocfs2/xattr.c
<snip>
> +/*
> + * Take an existing entry and make it ready for the new value.  This
> + * won't allocate space, but it may free space.  It should be ready for
> + * ocfs2_xa_prepare_entry() to finish the work.
> + */
> +static int ocfs2_xa_reuse_entry(struct ocfs2_xa_loc *loc,
> +				struct ocfs2_xattr_info *xi,
> +				struct ocfs2_xattr_set_ctxt *ctxt)
> +{
> +	int rc = 0;
> +	int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len);
> +	char *nameval_buf;
> +	int xe_local = ocfs2_xattr_is_local(loc->xl_entry);
> +	int xi_local = xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE;
> +
> +	BUG_ON(OCFS2_XATTR_SIZE(loc->xl_entry->xe_name_len) !=
> +	       name_size);
> +
> +	nameval_buf = ocfs2_xa_offset_pointer(loc,
> +				le16_to_cpu(loc->xl_entry->xe_name_offset));
> +	if (xe_local) {
> +		memset(nameval_buf + name_size, 0,
> +		       namevalue_size_xe(loc->xl_entry) - name_size);
> +		if (!xi_local)
> +			ocfs2_xa_install_value_root(loc);
> +	} else {
> +		if (xi_local) {
> +			rc = ocfs2_xa_value_truncate(loc, 0, ctxt);
> +			if (rc < 0) {
> +				mlog_errno(rc);
> +				goto out;
> +			}
> +			memset(nameval_buf + name_size, 0,
> +			       namevalue_size_xe(loc->xl_entry) -
> +			       name_size);
> +		} else if (le64_to_cpu(loc->xl_entry->xe_value_size) >
> +			   xi->xi_value_len) {
> +			rc = ocfs2_xa_value_truncate(loc, xi->xi_value_len,
> +						     ctxt);
 From your comments above, we don't allocate space. I am just curious 
why we can't extend it here if value_size < xi->xi_value_len?
> +			if (rc < 0) {
> +				mlog_errno(rc);
> +				goto out;
> +			}
> +		}
> +	}
> +
> +	loc->xl_entry->xe_value_size = cpu_to_le64(xi->xi_value_len);
> +	ocfs2_xattr_set_local(loc->xl_entry, xi_local);
> +
> +out:
> +	return rc;
> +}
> +
>  /*
>   * Prepares loc->xl_entry to receive the new xattr.  This includes
>   * properly setting up the name+value pair region.  If loc->xl_entry
> @@ -2027,11 +1974,10 @@ static void ocfs2_xa_remove_entry(struct ocfs2_xa_loc *loc)
>   */
>  static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc,
>  				  struct ocfs2_xattr_info *xi,
> -				  u32 name_hash)
> +				  u32 name_hash,
> +				  struct ocfs2_xattr_set_ctxt *ctxt)
>  {
>  	int rc = 0;
> -	int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len);
> -	char *nameval_buf;
>  
>  	if (!xi->xi_value) {
>  		ocfs2_xa_remove_entry(loc);
> @@ -2044,13 +1990,10 @@ static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc,
>  
>  	if (loc->xl_entry) {
>  		if (ocfs2_xa_can_reuse_entry(loc, xi)) {
> -			nameval_buf = ocfs2_xa_offset_pointer(loc,
> -				le16_to_cpu(loc->xl_entry->xe_name_offset));
> -			memset(nameval_buf + name_size, 0,
> -			       namevalue_size_xe(loc->xl_entry) - name_size);
> -			loc->xl_entry->xe_value_size =
> -				cpu_to_le64(xi->xi_value_len);
> -			goto out;
> +			rc = ocfs2_xa_reuse_entry(loc, xi, ctxt);
> +			if (rc)
> +				goto out;
> +			goto alloc_value;
As I said above in xa_reuse_entry, if we have already "alloc value" in 
ocfs2_xa_reuse_entry, we don't need to goto it again?
>  		}
>  
>  		ocfs2_xa_wipe_namevalue(loc);

>  static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc,
<snip>
> @@ -2336,28 +2195,6 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
>  	if (ret < 0)
>  		mlog_errno(ret);
>  
> -	if (!ret && xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
> -		/*
> -		 * Set value outside in B tree.
> -		 * This is the second step for value size > INLINE_SIZE.
> -		 */
> -		size_t offs = le16_to_cpu(xs->here->xe_name_offset);
> -		ret = ocfs2_xattr_set_value_outside(inode, xi, xs, ctxt,
> -						    &vb, offs);
> -		if (ret < 0) {
> -			int ret2;
> -
> -			mlog_errno(ret);
> -			/*
> -			 * If set value outside failed, we have to clean
> -			 * the junk tree root we have already set in local.
> -			 */
> -			ret2 = ocfs2_xattr_cleanup(inode, ctxt->handle,
> -						   xi, xs, &vb, offs);
you just removed this part which will remove the entry if we fail in 
cluster extension. I haven't seen some new implementation like that. Am 
I missing something here?
> -			if (ret2 < 0)
> -				mlog_errno(ret2);
> -		}
> -	}
>  out:
>  	return ret;
>  }

Regards,
Tao



More information about the Ocfs2-devel mailing list