Skip to content

Commit 1e9d62d

Browse files
niejtytso
authored andcommitted
ext4: optimize ea_inode block expansion
Copy ea data from inode entry when expanding ea block if possible. Then remove the ea entry if expansion success. Thus memcpy to a temporary buffer may be avoided. If the expansion fails, we do not need to recovery the removed ea entry neither in this way. Reported-by: [email protected] Link: https://syzkaller.appspot.com/bug?id=3613786cb88c93aa1c6a279b1df6a7b201347d08 Link: https://lore.kernel.org/r/[email protected] Cc: [email protected] Signed-off-by: Jun Nie <[email protected]> Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 08abd04 commit 1e9d62d

File tree

1 file changed

+17
-11
lines changed

1 file changed

+17
-11
lines changed

fs/ext4/xattr.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2600,9 +2600,8 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
26002600

26012601
is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
26022602
bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
2603-
buffer = kvmalloc(value_size, GFP_NOFS);
26042603
b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS);
2605-
if (!is || !bs || !buffer || !b_entry_name) {
2604+
if (!is || !bs || !b_entry_name) {
26062605
error = -ENOMEM;
26072606
goto out;
26082607
}
@@ -2614,12 +2613,18 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
26142613

26152614
/* Save the entry name and the entry value */
26162615
if (entry->e_value_inum) {
2616+
buffer = kvmalloc(value_size, GFP_NOFS);
2617+
if (!buffer) {
2618+
error = -ENOMEM;
2619+
goto out;
2620+
}
2621+
26172622
error = ext4_xattr_inode_get(inode, entry, buffer, value_size);
26182623
if (error)
26192624
goto out;
26202625
} else {
26212626
size_t value_offs = le16_to_cpu(entry->e_value_offs);
2622-
memcpy(buffer, (void *)IFIRST(header) + value_offs, value_size);
2627+
buffer = (void *)IFIRST(header) + value_offs;
26232628
}
26242629

26252630
memcpy(b_entry_name, entry->e_name, entry->e_name_len);
@@ -2634,25 +2639,26 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
26342639
if (error)
26352640
goto out;
26362641

2637-
/* Remove the chosen entry from the inode */
2638-
error = ext4_xattr_ibody_set(handle, inode, &i, is);
2639-
if (error)
2640-
goto out;
2641-
26422642
i.value = buffer;
26432643
i.value_len = value_size;
26442644
error = ext4_xattr_block_find(inode, &i, bs);
26452645
if (error)
26462646
goto out;
26472647

2648-
/* Add entry which was removed from the inode into the block */
2648+
/* Move ea entry from the inode into the block */
26492649
error = ext4_xattr_block_set(handle, inode, &i, bs);
26502650
if (error)
26512651
goto out;
2652-
error = 0;
2652+
2653+
/* Remove the chosen entry from the inode */
2654+
i.value = NULL;
2655+
i.value_len = 0;
2656+
error = ext4_xattr_ibody_set(handle, inode, &i, is);
2657+
26532658
out:
26542659
kfree(b_entry_name);
2655-
kvfree(buffer);
2660+
if (entry->e_value_inum && buffer)
2661+
kvfree(buffer);
26562662
if (is)
26572663
brelse(is->iloc.bh);
26582664
if (bs)

0 commit comments

Comments
 (0)