Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9dc47400 authored by Joel Becker's avatar Joel Becker
Browse files

ocfs2: Handle value tree roots in ocfs2_xa_set_inline_value()



Previously the xattr code would send in a fake value, containing a tree
root, to the function that installed name+value pairs.  Instead, we pass
the real value to ocfs2_xa_set_inline_value(), and it notices that the
value cannot fit.  Thus, it installs a tree root.

Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
parent 69a3e539
Loading
Loading
Loading
Loading
+16 −38
Original line number Original line Diff line number Diff line
@@ -1968,14 +1968,19 @@ static void ocfs2_xa_store_inline_value(struct ocfs2_xa_loc *loc,
{
{
	int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset);
	int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset);
	int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len);
	int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len);
	int size = namevalue_size_xi(xi);
	int inline_value_size = namevalue_size_xi(xi) - name_size;
	const void *value = xi->xi_value;
	char *nameval_buf;
	char *nameval_buf;


	if (!xi->xi_value)
	if (!xi->xi_value)
		return;
		return;


	if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
		value = &def_xv;
		inline_value_size = OCFS2_XATTR_ROOT_SIZE;
	}
	nameval_buf = ocfs2_xa_offset_pointer(loc, nameval_offset);
	nameval_buf = ocfs2_xa_offset_pointer(loc, nameval_offset);
	memcpy(nameval_buf + name_size, xi->xi_value, size - name_size);
	memcpy(nameval_buf + name_size, value, inline_value_size);
}
}


static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc,
static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc,
@@ -2054,13 +2059,6 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
	u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name,
	u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name,
					      xi->xi_name_len);
					      xi->xi_name_len);
	struct ocfs2_xa_loc loc;
	struct ocfs2_xa_loc loc;
	struct ocfs2_xattr_info xi_l = {
		.xi_name_index = xi->xi_name_index,
		.xi_name = xi->xi_name,
		.xi_name_len = xi->xi_name_len,
		.xi_value = xi->xi_value,
		.xi_value_len = xi->xi_value_len,
	};
	struct ocfs2_xattr_value_buf vb = {
	struct ocfs2_xattr_value_buf vb = {
		.vb_bh = xs->xattr_bh,
		.vb_bh = xs->xattr_bh,
		.vb_access = ocfs2_journal_access_di,
		.vb_access = ocfs2_journal_access_di,
@@ -2090,17 +2088,10 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
		free += ocfs2_xe_entry_usage(xs->here);
		free += ocfs2_xe_entry_usage(xs->here);


	/* Check free space in inode or block */
	/* Check free space in inode or block */
	if (xi->xi_value) {
	if (xi->xi_value && (free < ocfs2_xi_entry_usage(xi))) {
		if (free < ocfs2_xi_entry_usage(xi)) {
		ret = -ENOSPC;
		ret = -ENOSPC;
		goto out;
		goto out;
	}
	}
		if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
			size_l = namevalue_size_xi(xi);
			xi_l.xi_value = (void *)&def_xv;
			xi_l.xi_value_len = OCFS2_XATTR_ROOT_SIZE;
		}
	}


	if (!xs->not_found) {
	if (!xs->not_found) {
		/* For existing extended attribute */
		/* For existing extended attribute */
@@ -5255,8 +5246,7 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode,
					   handle_t *handle,
					   handle_t *handle,
					   struct ocfs2_xattr_info *xi,
					   struct ocfs2_xattr_info *xi,
					   struct ocfs2_xattr_search *xs,
					   struct ocfs2_xattr_search *xs,
					   u32 name_hash,
					   u32 name_hash)
					   int local)
{
{
	int ret;
	int ret;
	u64 blkno;
	u64 blkno;
@@ -5571,13 +5561,14 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
				     struct ocfs2_xattr_search *xs,
				     struct ocfs2_xattr_search *xs,
				     struct ocfs2_xattr_set_ctxt *ctxt)
				     struct ocfs2_xattr_set_ctxt *ctxt)
{
{
	int ret, local = 1;
	int ret;
	size_t value_len;
	size_t value_len;
	char *val = (char *)xi->xi_value;
	char *val = (char *)xi->xi_value;
	struct ocfs2_xattr_entry *xe = xs->here;
	struct ocfs2_xattr_entry *xe = xs->here;
	u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name,
	u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name,
					      xi->xi_name_len);
					      xi->xi_name_len);


	value_len = xi->xi_value_len;
	if (!xs->not_found && !ocfs2_xattr_is_local(xe)) {
	if (!xs->not_found && !ocfs2_xattr_is_local(xe)) {
		/*
		/*
		 * We need to truncate the xattr storage first.
		 * We need to truncate the xattr storage first.
@@ -5591,9 +5582,7 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
		 * the modification to the xattr block will be done
		 * the modification to the xattr block will be done
		 * by following steps.
		 * by following steps.
		 */
		 */
		if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE)
		if (xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE)
			value_len = xi->xi_value_len;
		else
			value_len = 0;
			value_len = 0;


		ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs,
		ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs,
@@ -5606,26 +5595,15 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
			goto set_value_outside;
			goto set_value_outside;
	}
	}


	value_len = xi->xi_value_len;
	/* So we have to handle the inside block change now. */
	/* So we have to handle the inside block change now. */
	if (value_len > OCFS2_XATTR_INLINE_SIZE) {
		/*
		 * If the new value will be stored outside of block,
		 * initalize a new empty value root and insert it first.
		 */
		local = 0;
		xi->xi_value = &def_xv;
		xi->xi_value_len = OCFS2_XATTR_ROOT_SIZE;
	}

	ret = ocfs2_xattr_set_entry_in_bucket(inode, ctxt->handle, xi, xs,
	ret = ocfs2_xattr_set_entry_in_bucket(inode, ctxt->handle, xi, xs,
					      name_hash, local);
					      name_hash);
	if (ret) {
	if (ret) {
		mlog_errno(ret);
		mlog_errno(ret);
		goto out;
		goto out;
	}
	}


	if (value_len <= OCFS2_XATTR_INLINE_SIZE)
	if (xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE)
		goto out;
		goto out;


	/* allocate the space now for the outside block storage. */
	/* allocate the space now for the outside block storage. */