add patch fast-symlink-test-should-not-rely-on-i_blocks
[ext4-patch-queue.git] / fix-ext4_xattr_move-to-block
blobf03adadbe3b11aa796b14496c4404d0cb3c6c4d7
1 ext4: fix ext4_xattr_move_to_block()
3 From: Tahsin Erdogan <tahsin@google.com>
5 When moving xattr entries from inline area to a xattr block, entries
6 that refer to external xattr inodes need special handling because
7 value data is not available in the inline area but rather should be
8 read from its external inode.
10 Signed-off-by: Tahsin Erdogan <tahsin@google.com>
11 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
12 ---
13  fs/ext4/xattr.c | 19 +++++++++++++------
14  1 file changed, 13 insertions(+), 6 deletions(-)
16 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
17 index 6a6bee246873..9c243b3510b7 100644
18 --- a/fs/ext4/xattr.c
19 +++ b/fs/ext4/xattr.c
20 @@ -1658,18 +1658,16 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
21         struct ext4_xattr_ibody_find *is = NULL;
22         struct ext4_xattr_block_find *bs = NULL;
23         char *buffer = NULL, *b_entry_name = NULL;
24 -       size_t value_offs, value_size;
25 +       size_t value_size = le32_to_cpu(entry->e_value_size);
26         struct ext4_xattr_info i = {
27                 .value = NULL,
28                 .value_len = 0,
29                 .name_index = entry->e_name_index,
30 +               .in_inode = !!entry->e_value_inum,
31         };
32         struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode);
33         int error;
35 -       value_offs = le16_to_cpu(entry->e_value_offs);
36 -       value_size = le32_to_cpu(entry->e_value_size);
38         is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
39         bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
40         buffer = kmalloc(value_size, GFP_NOFS);
41 @@ -1685,7 +1683,17 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
42         bs->bh = NULL;
44         /* Save the entry name and the entry value */
45 -       memcpy(buffer, (void *)IFIRST(header) + value_offs, value_size);
46 +       if (entry->e_value_inum) {
47 +               error = ext4_xattr_inode_get(inode,
48 +                                            le32_to_cpu(entry->e_value_inum),
49 +                                            buffer, value_size);
50 +               if (error)
51 +                       goto out;
52 +       } else {
53 +               size_t value_offs = le16_to_cpu(entry->e_value_offs);
54 +               memcpy(buffer, (void *)IFIRST(header) + value_offs, value_size);
55 +       }
57         memcpy(b_entry_name, entry->e_name, entry->e_name_len);
58         b_entry_name[entry->e_name_len] = '\0';
59         i.name = b_entry_name;
60 @@ -1703,7 +1711,6 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
61         if (error)
62                 goto out;
64 -       i.name = b_entry_name;
65         i.value = buffer;
66         i.value_len = value_size;
67         error = ext4_xattr_block_find(inode, &i, bs);
68 -- 
69 2.13.1.611.g7e3b11ae1-goog