summaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/xattr.c50
1 files changed, 26 insertions, 24 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 174d4e4a295f..354c55c3f70c 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -77,8 +77,9 @@ static void ext4_xattr_block_cache_insert(struct mb_cache *,
77static struct buffer_head * 77static struct buffer_head *
78ext4_xattr_block_cache_find(struct inode *, struct ext4_xattr_header *, 78ext4_xattr_block_cache_find(struct inode *, struct ext4_xattr_header *,
79 struct mb_cache_entry **); 79 struct mb_cache_entry **);
80static void ext4_xattr_rehash(struct ext4_xattr_header *, 80static void ext4_xattr_hash_entry(struct ext4_xattr_entry *entry,
81 struct ext4_xattr_entry *); 81 void *value_base);
82static void ext4_xattr_rehash(struct ext4_xattr_header *);
82 83
83static const struct xattr_handler * const ext4_xattr_handler_map[] = { 84static const struct xattr_handler * const ext4_xattr_handler_map[] = {
84 [EXT4_XATTR_INDEX_USER] = &ext4_xattr_user_handler, 85 [EXT4_XATTR_INDEX_USER] = &ext4_xattr_user_handler,
@@ -1467,7 +1468,8 @@ static int ext4_xattr_inode_lookup_create(handle_t *handle, struct inode *inode,
1467 1468
1468static int ext4_xattr_set_entry(struct ext4_xattr_info *i, 1469static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
1469 struct ext4_xattr_search *s, 1470 struct ext4_xattr_search *s,
1470 handle_t *handle, struct inode *inode) 1471 handle_t *handle, struct inode *inode,
1472 bool is_block)
1471{ 1473{
1472 struct ext4_xattr_entry *last; 1474 struct ext4_xattr_entry *last;
1473 struct ext4_xattr_entry *here = s->here; 1475 struct ext4_xattr_entry *here = s->here;
@@ -1531,8 +1533,8 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
1531 * attribute block so that a long value does not occupy the 1533 * attribute block so that a long value does not occupy the
1532 * whole space and prevent futher entries being added. 1534 * whole space and prevent futher entries being added.
1533 */ 1535 */
1534 if (ext4_has_feature_ea_inode(inode->i_sb) && new_size && 1536 if (ext4_has_feature_ea_inode(inode->i_sb) &&
1535 (s->end - s->base) == i_blocksize(inode) && 1537 new_size && is_block &&
1536 (min_offs + old_size - new_size) < 1538 (min_offs + old_size - new_size) <
1537 EXT4_XATTR_BLOCK_RESERVE(inode)) { 1539 EXT4_XATTR_BLOCK_RESERVE(inode)) {
1538 ret = -ENOSPC; 1540 ret = -ENOSPC;
@@ -1662,6 +1664,13 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
1662 } 1664 }
1663 here->e_value_size = cpu_to_le32(i->value_len); 1665 here->e_value_size = cpu_to_le32(i->value_len);
1664 } 1666 }
1667
1668 if (is_block) {
1669 if (i->value)
1670 ext4_xattr_hash_entry(here, s->base);
1671 ext4_xattr_rehash((struct ext4_xattr_header *)s->base);
1672 }
1673
1665 ret = 0; 1674 ret = 0;
1666out: 1675out:
1667 iput(old_ea_inode); 1676 iput(old_ea_inode);
@@ -1751,14 +1760,11 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
1751 mb_cache_entry_delete(ea_block_cache, hash, 1760 mb_cache_entry_delete(ea_block_cache, hash,
1752 bs->bh->b_blocknr); 1761 bs->bh->b_blocknr);
1753 ea_bdebug(bs->bh, "modifying in-place"); 1762 ea_bdebug(bs->bh, "modifying in-place");
1754 error = ext4_xattr_set_entry(i, s, handle, inode); 1763 error = ext4_xattr_set_entry(i, s, handle, inode,
1755 if (!error) { 1764 true /* is_block */);
1756 if (!IS_LAST_ENTRY(s->first)) 1765 if (!error)
1757 ext4_xattr_rehash(header(s->base),
1758 s->here);
1759 ext4_xattr_block_cache_insert(ea_block_cache, 1766 ext4_xattr_block_cache_insert(ea_block_cache,
1760 bs->bh); 1767 bs->bh);
1761 }
1762 ext4_xattr_block_csum_set(inode, bs->bh); 1768 ext4_xattr_block_csum_set(inode, bs->bh);
1763 unlock_buffer(bs->bh); 1769 unlock_buffer(bs->bh);
1764 if (error == -EFSCORRUPTED) 1770 if (error == -EFSCORRUPTED)
@@ -1818,7 +1824,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
1818 s->end = s->base + sb->s_blocksize; 1824 s->end = s->base + sb->s_blocksize;
1819 } 1825 }
1820 1826
1821 error = ext4_xattr_set_entry(i, s, handle, inode); 1827 error = ext4_xattr_set_entry(i, s, handle, inode, true /* is_block */);
1822 if (error == -EFSCORRUPTED) 1828 if (error == -EFSCORRUPTED)
1823 goto bad_block; 1829 goto bad_block;
1824 if (error) 1830 if (error)
@@ -1841,9 +1847,6 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
1841 } 1847 }
1842 } 1848 }
1843 1849
1844 if (!IS_LAST_ENTRY(s->first))
1845 ext4_xattr_rehash(header(s->base), s->here);
1846
1847inserted: 1850inserted:
1848 if (!IS_LAST_ENTRY(s->first)) { 1851 if (!IS_LAST_ENTRY(s->first)) {
1849 new_bh = ext4_xattr_block_cache_find(inode, header(s->base), 1852 new_bh = ext4_xattr_block_cache_find(inode, header(s->base),
@@ -2076,7 +2079,7 @@ int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode,
2076 2079
2077 if (EXT4_I(inode)->i_extra_isize == 0) 2080 if (EXT4_I(inode)->i_extra_isize == 0)
2078 return -ENOSPC; 2081 return -ENOSPC;
2079 error = ext4_xattr_set_entry(i, s, handle, inode); 2082 error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */);
2080 if (error) { 2083 if (error) {
2081 if (error == -ENOSPC && 2084 if (error == -ENOSPC &&
2082 ext4_has_inline_data(inode)) { 2085 ext4_has_inline_data(inode)) {
@@ -2088,7 +2091,8 @@ int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode,
2088 error = ext4_xattr_ibody_find(inode, i, is); 2091 error = ext4_xattr_ibody_find(inode, i, is);
2089 if (error) 2092 if (error)
2090 return error; 2093 return error;
2091 error = ext4_xattr_set_entry(i, s, handle, inode); 2094 error = ext4_xattr_set_entry(i, s, handle, inode,
2095 false /* is_block */);
2092 } 2096 }
2093 if (error) 2097 if (error)
2094 return error; 2098 return error;
@@ -2114,7 +2118,7 @@ static int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
2114 2118
2115 if (EXT4_I(inode)->i_extra_isize == 0) 2119 if (EXT4_I(inode)->i_extra_isize == 0)
2116 return -ENOSPC; 2120 return -ENOSPC;
2117 error = ext4_xattr_set_entry(i, s, handle, inode); 2121 error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */);
2118 if (error) 2122 if (error)
2119 return error; 2123 return error;
2120 header = IHDR(inode, ext4_raw_inode(&is->iloc)); 2124 header = IHDR(inode, ext4_raw_inode(&is->iloc));
@@ -2940,8 +2944,8 @@ ext4_xattr_block_cache_find(struct inode *inode,
2940 * 2944 *
2941 * Compute the hash of an extended attribute. 2945 * Compute the hash of an extended attribute.
2942 */ 2946 */
2943static inline void ext4_xattr_hash_entry(struct ext4_xattr_header *header, 2947static void ext4_xattr_hash_entry(struct ext4_xattr_entry *entry,
2944 struct ext4_xattr_entry *entry) 2948 void *value_base)
2945{ 2949{
2946 __u32 hash = 0; 2950 __u32 hash = 0;
2947 char *name = entry->e_name; 2951 char *name = entry->e_name;
@@ -2954,7 +2958,7 @@ static inline void ext4_xattr_hash_entry(struct ext4_xattr_header *header,
2954 } 2958 }
2955 2959
2956 if (!entry->e_value_inum && entry->e_value_size) { 2960 if (!entry->e_value_inum && entry->e_value_size) {
2957 __le32 *value = (__le32 *)((char *)header + 2961 __le32 *value = (__le32 *)((char *)value_base +
2958 le16_to_cpu(entry->e_value_offs)); 2962 le16_to_cpu(entry->e_value_offs));
2959 for (n = (le32_to_cpu(entry->e_value_size) + 2963 for (n = (le32_to_cpu(entry->e_value_size) +
2960 EXT4_XATTR_ROUND) >> EXT4_XATTR_PAD_BITS; n; n--) { 2964 EXT4_XATTR_ROUND) >> EXT4_XATTR_PAD_BITS; n; n--) {
@@ -2976,13 +2980,11 @@ static inline void ext4_xattr_hash_entry(struct ext4_xattr_header *header,
2976 * 2980 *
2977 * Re-compute the extended attribute hash value after an entry has changed. 2981 * Re-compute the extended attribute hash value after an entry has changed.
2978 */ 2982 */
2979static void ext4_xattr_rehash(struct ext4_xattr_header *header, 2983static void ext4_xattr_rehash(struct ext4_xattr_header *header)
2980 struct ext4_xattr_entry *entry)
2981{ 2984{
2982 struct ext4_xattr_entry *here; 2985 struct ext4_xattr_entry *here;
2983 __u32 hash = 0; 2986 __u32 hash = 0;
2984 2987
2985 ext4_xattr_hash_entry(header, entry);
2986 here = ENTRY(header+1); 2988 here = ENTRY(header+1);
2987 while (!IS_LAST_ENTRY(here)) { 2989 while (!IS_LAST_ENTRY(here)) {
2988 if (!here->e_hash) { 2990 if (!here->e_hash) {