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: Joel Becker <joel.becker@oracle.com>
This commit is contained in:
parent
69a3e539d0
commit
9dc474005d
|
@ -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 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;
|
||||
|
||||
if (!xi->xi_value)
|
||||
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);
|
||||
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,
|
||||
|
@ -2054,13 +2059,6 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
|
|||
u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name,
|
||||
xi->xi_name_len);
|
||||
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 = {
|
||||
.vb_bh = xs->xattr_bh,
|
||||
.vb_access = ocfs2_journal_access_di,
|
||||
|
@ -2090,16 +2088,9 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
|
|||
free += ocfs2_xe_entry_usage(xs->here);
|
||||
|
||||
/* Check free space in inode or block */
|
||||
if (xi->xi_value) {
|
||||
if (free < ocfs2_xi_entry_usage(xi)) {
|
||||
ret = -ENOSPC;
|
||||
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 (xi->xi_value && (free < ocfs2_xi_entry_usage(xi))) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!xs->not_found) {
|
||||
|
@ -5255,8 +5246,7 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode,
|
|||
handle_t *handle,
|
||||
struct ocfs2_xattr_info *xi,
|
||||
struct ocfs2_xattr_search *xs,
|
||||
u32 name_hash,
|
||||
int local)
|
||||
u32 name_hash)
|
||||
{
|
||||
int ret;
|
||||
u64 blkno;
|
||||
|
@ -5571,13 +5561,14 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
|
|||
struct ocfs2_xattr_search *xs,
|
||||
struct ocfs2_xattr_set_ctxt *ctxt)
|
||||
{
|
||||
int ret, local = 1;
|
||||
int ret;
|
||||
size_t value_len;
|
||||
char *val = (char *)xi->xi_value;
|
||||
struct ocfs2_xattr_entry *xe = xs->here;
|
||||
u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name,
|
||||
xi->xi_name_len);
|
||||
|
||||
value_len = xi->xi_value_len;
|
||||
if (!xs->not_found && !ocfs2_xattr_is_local(xe)) {
|
||||
/*
|
||||
* 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
|
||||
* by following steps.
|
||||
*/
|
||||
if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE)
|
||||
value_len = xi->xi_value_len;
|
||||
else
|
||||
if (xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE)
|
||||
value_len = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
value_len = xi->xi_value_len;
|
||||
/* 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,
|
||||
name_hash, local);
|
||||
name_hash);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (value_len <= OCFS2_XATTR_INLINE_SIZE)
|
||||
if (xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE)
|
||||
goto out;
|
||||
|
||||
/* allocate the space now for the outside block storage. */
|
||||
|
|
Loading…
Reference in New Issue