mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] ext4: do not accept rec_len 0 for block sizes below 64k
@ 2026-10-06 11:15 hengyul
  2026-10-06 16:16 ` Jan Kara
  2026-10-08  2:38 ` Baokun Li
  0 siblings, 2 replies; 4+ messages in thread
From: hengyul @ 2026-10-06 11:15 UTC (permalink / raw)
  To: tytso, linux-ext4
  Cc: adilger.kernel, libaokun, jack, ojaswin, ritesh.list, yi.zhang,
	linux-kernel, Hengyu Liang, stable

From: Hengyu Liang <hengyul@cs.unc.edu>

Commit afa6d5a16bf2 ("ext4: remove PAGE_SIZE checks for rec_len
conversion") made ext4_rec_len_from_disk() read a rec_len of 0 as "this
entry covers the whole block" for every block size.

However, this special value only exists for block sizes of 64k and
more. With smaller blocks, a rec_len of 0 means that the directory
block is corrupted. As of now, a directory block that has been
overwritten with zeroes is treated as an empty block. The kernel no
longer reports the corruption and can store new entries in that block,
while e2fsck still reports the block as corrupted.

The issue can be reproduced on a file system without metadata_csum:

    mke2fs -q -t ext4 -b 1024 -O ^metadata_csum,^dir_index img 8M
    mount -o loop img /mnt
    mkdir /mnt/d
    for i in $(seq 100); do touch /mnt/d/file_with_a_long_name_$i; done
    umount /mnt
    dd if=/dev/zero of=img bs=1024 count=1 conv=notrunc \
        seek=$(debugfs -R "bmap d 1" img)
    mount -o loop img /mnt
    touch /mnt/d/new

Before commit afa6d5a16bf2 ("ext4: remove PAGE_SIZE checks for rec_len
conversion"), the last command fails with "Structure needs cleaning".
After that commit, it succeeds.

This patch makes ext4_rec_len_from_disk() return the on-disk value
unchanged when the block size is below 64k, as e2fsprogs does.

Fixes: afa6d5a16bf2 ("ext4: remove PAGE_SIZE checks for rec_len conversion")
Cc: stable@vger.kernel.org
Signed-off-by: Hengyu Liang <hengyul@cs.unc.edu>
---
 fs/ext4/ext4.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 724a27e8be61..ab716a5ad6da 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2611,6 +2611,13 @@ ext4_rec_len_from_disk(__le16 dlen, unsigned blocksize)
 {
 	unsigned len = le16_to_cpu(dlen);
 
+	/*
+	 * Only blocks of 64k and more need the special encoding of rec_len.
+	 * For smaller blocks 0 and EXT4_MAX_REC_LEN are not valid lengths
+	 * and must not be taken for an entry that spans the whole block.
+	 */
+	if (blocksize < 65536)
+		return len;
 	if (len == EXT4_MAX_REC_LEN || len == 0)
 		return blocksize;
 	return (len & 65532) | ((len & 3) << 16);
-- 
2.53.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-08  2:43 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-06 11:15 [PATCH] ext4: do not accept rec_len 0 for block sizes below 64k hengyul
2026-10-06 16:16 ` Jan Kara
2026-10-07  7:43   ` Andreas Dilger
2026-10-08  2:38 ` Baokun Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®