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

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
...@@ -1968,14 +1968,19 @@ static void ocfs2_xa_store_inline_value(struct ocfs2_xa_loc *loc, ...@@ -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, ...@@ -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,16 +2088,9 @@ static int ocfs2_xattr_set_entry(struct inode *inode, ...@@ -2090,16 +2088,9 @@ 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) {
...@@ -5255,8 +5246,7 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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. */
......
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