diff options
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/xattr.c | 50 |
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 *, | |||
77 | static struct buffer_head * | 77 | static struct buffer_head * |
78 | ext4_xattr_block_cache_find(struct inode *, struct ext4_xattr_header *, | 78 | ext4_xattr_block_cache_find(struct inode *, struct ext4_xattr_header *, |
79 | struct mb_cache_entry **); | 79 | struct mb_cache_entry **); |
80 | static void ext4_xattr_rehash(struct ext4_xattr_header *, | 80 | static void ext4_xattr_hash_entry(struct ext4_xattr_entry *entry, |
81 | struct ext4_xattr_entry *); | 81 | void *value_base); |
82 | static void ext4_xattr_rehash(struct ext4_xattr_header *); | ||
82 | 83 | ||
83 | static const struct xattr_handler * const ext4_xattr_handler_map[] = { | 84 | static 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 | ||
1468 | static int ext4_xattr_set_entry(struct ext4_xattr_info *i, | 1469 | static 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; |
1666 | out: | 1675 | out: |
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 | |||
1847 | inserted: | 1850 | inserted: |
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 | */ |
2943 | static inline void ext4_xattr_hash_entry(struct ext4_xattr_header *header, | 2947 | static 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 | */ |
2979 | static void ext4_xattr_rehash(struct ext4_xattr_header *header, | 2983 | static 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) { |