From 9ae9f2e9831d121d80871eddb08a80c625ae99d3 Mon Sep 17 00:00:00 2001 From: Gality <68463495+Gality369@users.noreply.github.com> Date: Sat, 9 May 2026 06:08:21 +0800 Subject: [PATCH] Linux: annotate nested xattr setattr znode locks zfs_setattr() updates both the target znode and its hidden xattr directory when ownership, mode, or project ID changes. The xattr directory uses the same z_acl_lock and z_lock classes as the parent znode, so lockdep reports recursive locking when the second znode's mutexes are acquired. This is a lockdep false positive rather than a real deadlock. attrzp is the target file's hidden xattr directory, and the code does not acquire these znode mutexes in the reverse order. Acquire the attrzp mutexes with mutex_enter_nested() so lockdep treats them as nested. Reviewed-by: Brian Behlendorf Signed-off-by: ZhengYuan Huang Co-authored-by: gality369 Closes #18506 --- module/os/linux/zfs/zfs_vnops_os.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c index e65f8123012..1e1e663b1f7 100644 --- a/module/os/linux/zfs/zfs_vnops_os.c +++ b/module/os/linux/zfs/zfs_vnops_os.c @@ -2434,9 +2434,13 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zidmap_t *mnt_ns) &zp->z_pflags, sizeof (zp->z_pflags)); if (attrzp) { + /* + * attrzp is zp's hidden xattr directory, so the second + * znode lock acquisition is nested rather than recursive. + */ if (mask & (ATTR_UID|ATTR_GID|ATTR_MODE)) - mutex_enter(&attrzp->z_acl_lock); - mutex_enter(&attrzp->z_lock); + mutex_enter_nested(&attrzp->z_acl_lock, NESTED_SINGLE); + mutex_enter_nested(&attrzp->z_lock, NESTED_SINGLE); SA_ADD_BULK_ATTR(xattr_bulk, xattr_count, SA_ZPL_FLAGS(zfsvfs), NULL, &attrzp->z_pflags, sizeof (attrzp->z_pflags));