summaryrefslogtreecommitdiffstats
path: root/fs/ext4/xattr.c
diff options
context:
space:
mode:
authorTahsin Erdogan <tahsin@google.com>2017-06-21 22:11:54 -0400
committerTheodore Ts'o <tytso@mit.edu>2017-06-21 22:11:54 -0400
commitf6109100ba8692c677cfdc88af1887a43263e63a (patch)
treea83af0e1c279216db190a4e5733bc0c5b2a69d5e /fs/ext4/xattr.c
parent9bb21cedda7cd69789e1f93d7d918f5ca48ba165 (diff)
ext4: fix ext4_xattr_move_to_block()
When moving xattr entries from inline area to a xattr block, entries that refer to external xattr inodes need special handling because value data is not available in the inline area but rather should be read from its external inode. Signed-off-by: Tahsin Erdogan <tahsin@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/xattr.c')
-rw-r--r--fs/ext4/xattr.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 2be891ffeda1..bd1e61a0c228 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -1656,18 +1656,16 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
1656 struct ext4_xattr_ibody_find *is = NULL; 1656 struct ext4_xattr_ibody_find *is = NULL;
1657 struct ext4_xattr_block_find *bs = NULL; 1657 struct ext4_xattr_block_find *bs = NULL;
1658 char *buffer = NULL, *b_entry_name = NULL; 1658 char *buffer = NULL, *b_entry_name = NULL;
1659 size_t value_offs, value_size; 1659 size_t value_size = le32_to_cpu(entry->e_value_size);
1660 struct ext4_xattr_info i = { 1660 struct ext4_xattr_info i = {
1661 .value = NULL, 1661 .value = NULL,
1662 .value_len = 0, 1662 .value_len = 0,
1663 .name_index = entry->e_name_index, 1663 .name_index = entry->e_name_index,
1664 .in_inode = !!entry->e_value_inum,
1664 }; 1665 };
1665 struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode); 1666 struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode);
1666 int error; 1667 int error;
1667 1668
1668 value_offs = le16_to_cpu(entry->e_value_offs);
1669 value_size = le32_to_cpu(entry->e_value_size);
1670
1671 is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS); 1669 is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
1672 bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS); 1670 bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
1673 buffer = kmalloc(value_size, GFP_NOFS); 1671 buffer = kmalloc(value_size, GFP_NOFS);
@@ -1683,7 +1681,17 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
1683 bs->bh = NULL; 1681 bs->bh = NULL;
1684 1682
1685 /* Save the entry name and the entry value */ 1683 /* Save the entry name and the entry value */
1686 memcpy(buffer, (void *)IFIRST(header) + value_offs, value_size); 1684 if (entry->e_value_inum) {
1685 error = ext4_xattr_inode_get(inode,
1686 le32_to_cpu(entry->e_value_inum),
1687 buffer, value_size);
1688 if (error)
1689 goto out;
1690 } else {
1691 size_t value_offs = le16_to_cpu(entry->e_value_offs);
1692 memcpy(buffer, (void *)IFIRST(header) + value_offs, value_size);
1693 }
1694
1687 memcpy(b_entry_name, entry->e_name, entry->e_name_len); 1695 memcpy(b_entry_name, entry->e_name, entry->e_name_len);
1688 b_entry_name[entry->e_name_len] = '\0'; 1696 b_entry_name[entry->e_name_len] = '\0';
1689 i.name = b_entry_name; 1697 i.name = b_entry_name;
@@ -1701,7 +1709,6 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
1701 if (error) 1709 if (error)
1702 goto out; 1710 goto out;
1703 1711
1704 i.name = b_entry_name;
1705 i.value = buffer; 1712 i.value = buffer;
1706 i.value_len = value_size; 1713 i.value_len = value_size;
1707 error = ext4_xattr_block_find(inode, &i, bs); 1714 error = ext4_xattr_block_find(inode, &i, bs);