diff options
author | Joel Becker <joel.becker@oracle.com> | 2009-08-17 22:56:01 -0400 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2010-02-26 18:41:10 -0500 |
commit | 9dc474005d0e34cf21d4b510f347e3942f24b021 (patch) | |
tree | f19e028c6f500802623a5c8256c64e434a79a2be /fs/ocfs2/xattr.c | |
parent | 69a3e539d083ac09aec92b8705b8ff2c2e5c810c (diff) |
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>
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r-- | fs/ocfs2/xattr.c | 54 |
1 files changed, 16 insertions, 38 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 4bf6ec849e19..6d362e2d3960 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -1968,14 +1968,19 @@ static void ocfs2_xa_store_inline_value(struct ocfs2_xa_loc *loc, | |||
1968 | { | 1968 | { |
1969 | int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset); | 1969 | int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset); |
1970 | int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len); | 1970 | int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len); |
1971 | int size = namevalue_size_xi(xi); | 1971 | int inline_value_size = namevalue_size_xi(xi) - name_size; |
1972 | const void *value = xi->xi_value; | ||
1972 | char *nameval_buf; | 1973 | char *nameval_buf; |
1973 | 1974 | ||
1974 | if (!xi->xi_value) | 1975 | if (!xi->xi_value) |
1975 | return; | 1976 | return; |
1976 | 1977 | ||
1978 | if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) { | ||
1979 | value = &def_xv; | ||
1980 | inline_value_size = OCFS2_XATTR_ROOT_SIZE; | ||
1981 | } | ||
1977 | nameval_buf = ocfs2_xa_offset_pointer(loc, nameval_offset); | 1982 | nameval_buf = ocfs2_xa_offset_pointer(loc, nameval_offset); |
1978 | memcpy(nameval_buf + name_size, xi->xi_value, size - name_size); | 1983 | memcpy(nameval_buf + name_size, value, inline_value_size); |
1979 | } | 1984 | } |
1980 | 1985 | ||
1981 | static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc, | 1986 | 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 | u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name, | 2059 | u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name, |
2055 | xi->xi_name_len); | 2060 | xi->xi_name_len); |
2056 | struct ocfs2_xa_loc loc; | 2061 | struct ocfs2_xa_loc loc; |
2057 | struct ocfs2_xattr_info xi_l = { | ||
2058 | .xi_name_index = xi->xi_name_index, | ||
2059 | .xi_name = xi->xi_name, | ||
2060 | .xi_name_len = xi->xi_name_len, | ||
2061 | .xi_value = xi->xi_value, | ||
2062 | .xi_value_len = xi->xi_value_len, | ||
2063 | }; | ||
2064 | struct ocfs2_xattr_value_buf vb = { | 2062 | struct ocfs2_xattr_value_buf vb = { |
2065 | .vb_bh = xs->xattr_bh, | 2063 | .vb_bh = xs->xattr_bh, |
2066 | .vb_access = ocfs2_journal_access_di, | 2064 | .vb_access = ocfs2_journal_access_di, |
@@ -2090,16 +2088,9 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
2090 | free += ocfs2_xe_entry_usage(xs->here); | 2088 | free += ocfs2_xe_entry_usage(xs->here); |
2091 | 2089 | ||
2092 | /* Check free space in inode or block */ | 2090 | /* Check free space in inode or block */ |
2093 | if (xi->xi_value) { | 2091 | if (xi->xi_value && (free < ocfs2_xi_entry_usage(xi))) { |
2094 | if (free < ocfs2_xi_entry_usage(xi)) { | 2092 | ret = -ENOSPC; |
2095 | ret = -ENOSPC; | 2093 | goto out; |
2096 | goto out; | ||
2097 | } | ||
2098 | if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) { | ||
2099 | size_l = namevalue_size_xi(xi); | ||
2100 | xi_l.xi_value = (void *)&def_xv; | ||
2101 | xi_l.xi_value_len = OCFS2_XATTR_ROOT_SIZE; | ||
2102 | } | ||
2103 | } | 2094 | } |
2104 | 2095 | ||
2105 | if (!xs->not_found) { | 2096 | if (!xs->not_found) { |
@@ -5255,8 +5246,7 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode, | |||
5255 | handle_t *handle, | 5246 | handle_t *handle, |
5256 | struct ocfs2_xattr_info *xi, | 5247 | struct ocfs2_xattr_info *xi, |
5257 | struct ocfs2_xattr_search *xs, | 5248 | struct ocfs2_xattr_search *xs, |
5258 | u32 name_hash, | 5249 | u32 name_hash) |
5259 | int local) | ||
5260 | { | 5250 | { |
5261 | int ret; | 5251 | int ret; |
5262 | u64 blkno; | 5252 | u64 blkno; |
@@ -5571,13 +5561,14 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode, | |||
5571 | struct ocfs2_xattr_search *xs, | 5561 | struct ocfs2_xattr_search *xs, |
5572 | struct ocfs2_xattr_set_ctxt *ctxt) | 5562 | struct ocfs2_xattr_set_ctxt *ctxt) |
5573 | { | 5563 | { |
5574 | int ret, local = 1; | 5564 | int ret; |
5575 | size_t value_len; | 5565 | size_t value_len; |
5576 | char *val = (char *)xi->xi_value; | 5566 | char *val = (char *)xi->xi_value; |
5577 | struct ocfs2_xattr_entry *xe = xs->here; | 5567 | struct ocfs2_xattr_entry *xe = xs->here; |
5578 | u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name, | 5568 | u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name, |
5579 | xi->xi_name_len); | 5569 | xi->xi_name_len); |
5580 | 5570 | ||
5571 | value_len = xi->xi_value_len; | ||
5581 | if (!xs->not_found && !ocfs2_xattr_is_local(xe)) { | 5572 | if (!xs->not_found && !ocfs2_xattr_is_local(xe)) { |
5582 | /* | 5573 | /* |
5583 | * We need to truncate the xattr storage first. | 5574 | * We need to truncate the xattr storage first. |
@@ -5591,9 +5582,7 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode, | |||
5591 | * the modification to the xattr block will be done | 5582 | * the modification to the xattr block will be done |
5592 | * by following steps. | 5583 | * by following steps. |
5593 | */ | 5584 | */ |
5594 | if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) | 5585 | if (xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE) |
5595 | value_len = xi->xi_value_len; | ||
5596 | else | ||
5597 | value_len = 0; | 5586 | value_len = 0; |
5598 | 5587 | ||
5599 | ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs, | 5588 | ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs, |
@@ -5606,26 +5595,15 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode, | |||
5606 | goto set_value_outside; | 5595 | goto set_value_outside; |
5607 | } | 5596 | } |
5608 | 5597 | ||
5609 | value_len = xi->xi_value_len; | ||
5610 | /* So we have to handle the inside block change now. */ | 5598 | /* So we have to handle the inside block change now. */ |
5611 | if (value_len > OCFS2_XATTR_INLINE_SIZE) { | ||
5612 | /* | ||
5613 | * If the new value will be stored outside of block, | ||
5614 | * initalize a new empty value root and insert it first. | ||
5615 | */ | ||
5616 | local = 0; | ||
5617 | xi->xi_value = &def_xv; | ||
5618 | xi->xi_value_len = OCFS2_XATTR_ROOT_SIZE; | ||
5619 | } | ||
5620 | |||
5621 | ret = ocfs2_xattr_set_entry_in_bucket(inode, ctxt->handle, xi, xs, | 5599 | ret = ocfs2_xattr_set_entry_in_bucket(inode, ctxt->handle, xi, xs, |
5622 | name_hash, local); | 5600 | name_hash); |
5623 | if (ret) { | 5601 | if (ret) { |
5624 | mlog_errno(ret); | 5602 | mlog_errno(ret); |
5625 | goto out; | 5603 | goto out; |
5626 | } | 5604 | } |
5627 | 5605 | ||
5628 | if (value_len <= OCFS2_XATTR_INLINE_SIZE) | 5606 | if (xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE) |
5629 | goto out; | 5607 | goto out; |
5630 | 5608 | ||
5631 | /* allocate the space now for the outside block storage. */ | 5609 | /* allocate the space now for the outside block storage. */ |