Viewing: ext4-symlink-xattr-inode-fix.patch

commit d0c75da783013e61c6c53bdd26337d72b3679961
Author:     Andreas Dilger <adilger@whamcloud.com>
AuthorDate: Sat Jun 21 08:55:51 2025 -0600
ext4: check fast symlink for ea_inode correctly

The check for a fast symlink in the presence of only an
external xattr inode is incorrect.  If a fast symlink does
not have an xattr block (i_file_acl == 0), but does have
an external xattr inode that increases inode i_blocks, then
the check for a fast symlink will incorrectly fail and
__ext4_iget()->ext4_ind_check_inode() will report an error
when the inode is next loaded into memory:

    # ln -s foo /mnt/tmp/bar
    # setfattr -h -n trusted.test \
               -v "$(head -200 /etc/services)" /mnt/tmp/bar
    # umount /mnt/tmp
    # mount /mnt/tmp
    # ls -l /mnt/tmp
    ls: cannot access '/mnt/tmp/bar': Structure needs cleaning
    total 4
     ? l?????????? ? ?    ?        ?            ? bar
    # dmesg | tail -1
    EXT4-fs error (device dm-8): __ext4_iget:5098:
        inode #24578: block 7303014: comm ls: invalid block

The ext4_inode_is_fast_symlink() check should use the
superblock EA_INODE feature flag, not EXT4_EA_INODE_FL,
since the latter is only set on the xattr inode itself,
and not on the inode that references it.

Linux-commit: b4cc4a4077268522e3d0d34de4b2dc144e2330fa

Fixes: fc82228a5e38 ("ext4: support fast symlinks from ext3 file systems")
Signed-off-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Li Dongyang <dongyangli@ddn.com>
Reviewed-by: Alex Zhuravlev <bzzz@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Change-Id: Ia7c1c59fcc005a3be11435325a96b809592540e5
Reviewed-on: https://review.whamcloud.com/59879

Index: linux-stage/fs/ext4/inode.c
===================================================================
--- linux-stage.orig/fs/ext4/inode.c
+++ linux-stage/fs/ext4/inode.c
@@ -148,7 +148,7 @@ static int ext4_meta_trans_blocks(struct
  */
 int ext4_inode_is_fast_symlink(struct inode *inode)
 {
-	if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) {
+	if (!ext4_has_feature_ea_inode(inode->i_sb)) {
 		int ea_blocks = EXT4_I(inode)->i_file_acl ?
 				EXT4_CLUSTER_SIZE(inode->i_sb) >> 9 : 0;