summaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
authorEric Whitney <enwlinux@gmail.com>2021-08-19 10:49:27 -0400
committerTheodore Ts'o <tytso@mit.edu>2021-09-09 10:52:05 -0400
commit948ca5f30e1df0c11eb5b0f410b9ceb97fa77ad9 (patch)
tree25ba4c1cc971df706a881e52b3361da419c7ca38 /fs/ext4/inode.c
parent0add491df4e5e2c8cc6eeeaa6dbcca50f932090c (diff)
downloadlinux-stable-948ca5f30e1df0c11eb5b0f410b9ceb97fa77ad9.tar.gz
linux-stable-948ca5f30e1df0c11eb5b0f410b9ceb97fa77ad9.tar.bz2
linux-stable-948ca5f30e1df0c11eb5b0f410b9ceb97fa77ad9.zip
ext4: enforce buffer head state assertion in ext4_da_map_blocks
Remove the code that re-initializes a buffer head with an invalid block number and BH_New and BH_Delay bits when a matching delayed and unwritten block has been found in the extent status cache. Replace it with assertions that verify the buffer head already has this state correctly set. The current code masked an inline data truncation bug that left stale entries in the extent status cache. With this change, generic/130 can be used to reproduce and detect that bug. Signed-off-by: Eric Whitney <enwlinux@gmail.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Link: https://lore.kernel.org/r/20210819144927.25163-3-enwlinux@gmail.com Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 8204176256c8..2a076d236ba1 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1706,13 +1706,16 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
}
/*
- * Delayed extent could be allocated by fallocate.
- * So we need to check it.
+ * the buffer head associated with a delayed and not unwritten
+ * block found in the extent status cache must contain an
+ * invalid block number and have its BH_New and BH_Delay bits
+ * set, reflecting the state assigned when the block was
+ * initially delayed allocated
*/
- if (ext4_es_is_delayed(&es) && !ext4_es_is_unwritten(&es)) {
- map_bh(bh, inode->i_sb, invalid_block);
- set_buffer_new(bh);
- set_buffer_delay(bh);
+ if (ext4_es_is_delonly(&es)) {
+ BUG_ON(bh->b_blocknr != invalid_block);
+ BUG_ON(!buffer_new(bh));
+ BUG_ON(!buffer_delay(bh));
return 0;
}