From: Gao Xiang Date: Wed, 28 Jan 2026 03:54:08 +0000 (+0800) Subject: erofs: mark inodes without acls in erofs_read_inode() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1729f7c67544b31569836f48f142e8f7c0952b26;p=thirdparty%2Fkernel%2Flinux.git erofs: mark inodes without acls in erofs_read_inode() Similar to commit 91ef18b567da ("ext4: mark inodes without acls in __ext4_iget()"), the ACL state won't be read when the file owner performs a lookup, and the RCU fast path for lookups won't work because the ACL state remains unknown. If there are no extended attributes, or if the xattr filter indicates that no ACL xattr is present, call cache_no_acl() directly. Reviewed-by: Hongbo Li Signed-off-by: Gao Xiang --- diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index d33816cff8139..2ecc28abd6cd0 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -137,6 +137,11 @@ static int erofs_read_inode(struct inode *inode) err = -EFSCORRUPTED; goto err_out; } + + if (IS_ENABLED(CONFIG_EROFS_FS_POSIX_ACL) && + erofs_inode_has_noacl(inode, ptr, ofs)) + cache_no_acl(inode); + switch (inode->i_mode & S_IFMT) { case S_IFDIR: vi->dot_omitted = (ifmt >> EROFS_I_DOT_OMITTED_BIT) & 1; diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c index 2ef9d6436b05e..b7da1ed83160b 100644 --- a/fs/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -587,6 +587,26 @@ struct posix_acl *erofs_get_acl(struct inode *inode, int type, bool rcu) kfree(value); return acl; } + +bool erofs_inode_has_noacl(struct inode *inode, void *kaddr, unsigned int ofs) +{ + static const unsigned int bitmask = + BIT(21) | /* system.posix_acl_default */ + BIT(30); /* system.posix_acl_access */ + struct erofs_sb_info *sbi = EROFS_I_SB(inode); + const struct erofs_xattr_ibody_header *ih = kaddr + ofs; + + if (EROFS_I(inode)->xattr_isize < sizeof(*ih)) + return true; + + if (erofs_sb_has_xattr_filter(sbi) && !sbi->xattr_filter_reserved && + !check_add_overflow(ofs, sizeof(*ih), &ofs) && + ofs <= i_blocksize(inode)) { + if ((le32_to_cpu(ih->h_name_filter) & bitmask) == bitmask) + return true; + } + return false; +} #endif #ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE diff --git a/fs/erofs/xattr.h b/fs/erofs/xattr.h index 4d0e58ff7a140..4465f7018a417 100644 --- a/fs/erofs/xattr.h +++ b/fs/erofs/xattr.h @@ -32,5 +32,5 @@ struct posix_acl *erofs_get_acl(struct inode *inode, int type, bool rcu); int erofs_xattr_fill_inode_fingerprint(struct erofs_inode_fingerprint *fp, struct inode *inode, const char *domain_id); - +bool erofs_inode_has_noacl(struct inode *inode, void *kaddr, unsigned int ofs); #endif