From nobody Fri Oct 2 10:08:34 2026 Received: from flow-b6-smtp.messagingengine.com (flow-b6-smtp.messagingengine.com [202.12.124.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C140E234994; Mon, 3 Aug 2026 01:37:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721034; cv=none; b=kqKF/7Fu8adxP+OpdLF5z9syO13X5WKY3L/+nF0LjWQREMqLVKkkLpiPUEip8/KrFjjXfHxiBeO3ULf5MI1pTO8pjoA3laZy7GEqStVReRcpM0Lm9P0GmlONsV3KklFdrC7m6q4YJh8MyQOLFEqrW0qnTsm6zFHbfAjfI0/VF6s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721034; c=relaxed/simple; bh=EbD5w2eeGlbaf9p46vs2K3OwQyCJTl1WmCBJVMY05AE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qaEJGNhJBhKLfOSjijCx9tj9ZG4DxtuV+pskVqvTx2dyS8M95iKN6nzi4RRBR7jcW1M1FmgrFclknJm041gS3yR+Py8A8wzZrXbeytlZOWEps27tw/tz0/gPPD7gH4e1JeklfcYsrR9OqSpY9u4P8Narp61yJacZiW/7nLSWQpU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net; spf=pass smtp.mailfrom=ownmail.net; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b=P2U6t07s; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=eRj1jwxS; arc=none smtp.client-ip=202.12.124.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ownmail.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b="P2U6t07s"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="eRj1jwxS" Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailflow.stl.internal (Postfix) with ESMTP id 781DD13000EE; Sun, 2 Aug 2026 21:37:11 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-06.internal (MEProxy); Sun, 02 Aug 2026 21:37:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ownmail.net; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to; s=fm3; t=1785721031; x=1785728231; bh=XcMpOwwDDQgPSkpRR6R3/4paVJIkORHFtV97iS/uiJc=; b= P2U6t07sJhEjHQkidyYxiD4jQQJfU5lT2R7KbkLMFPK2BUp66W8cJ6MokSWBOKkx Jm2hgAB+bm4bOWJ2VfB0mOWDeRwkWPzAztHnSm9g/a7LjsutgmGwMsjFIlJpDXgc t+pJERpALq/tKKknTT1RR+9NKHSunTb6J8rvunOBymq4+wkuxsECVn5qMfs/FDys 1ByoVR9okh6HmY0ytjX1YLWTNxqxRKnDuUuFAsC+e29BXfH25O2KkB9iH+npEbve L8Cgxl5uykYkuUJofBvLcbEWQztvqPD9gWkVuHn/8iNW+bjARuUWBuDPxIuvIYcP 4nFRKy/AinI+ZmVlcI3GOw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1785721031; x=1785728231; bh=X cMpOwwDDQgPSkpRR6R3/4paVJIkORHFtV97iS/uiJc=; b=eRj1jwxSKB7yQvR9v Mx8nM/Rn8b9FlcQURHiU1iQdBfBKIo7rOd874TFYIcknH3F8Ur+rJ8nzymg5K2SQ X7gaxbW7uXIx2xy0xxvswsJnVbjnPF+6kW6J5mYAeTLV4C1wy6gYk6cUse7ztvHd 8wdkrg7652gGZGV0B1NdUKvVjgYdBtCFe/h8Gk5rnLz456e3+62tJ8CO5EZSf5AN Kh1wiAqiADW6OmO/YplEV3K2AHtrlYZq6KYil+CuoFqZS+YRpt9/iAjdX2nJQlFF bpzelWub0AwNrGEs8ZbZ0/FBdz7Vd1U++zIY7avWXilQPT0+CEv15DlNl2VFwcDf 3QBiQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFswjlVGtOMO0DJ/yAygp0kikcHV2WSXHSGnlIkcuf0k9rLUdswY4SNsXMvUWMhfJ kpfPtsQuVQ8vSHADhVm4IRY0nolbqOkRQBDAEaT6PViWtUiGaZ1RuyP3TKdnsto1GxdvO6 EDjVnoxMaix/qwxYa/EnmBrWSMWR71Xsepg0lYJWsNgdazP7uMjE+vSD+hiwoRYUCYwqMd 8UCnzcTzoJOqEB2P0a4xlmt6Vi448YXJsDRRsyN3s901toR6OrLn7/rtKpBURTUpkDqxh0 ISJdNDy7NZx3er7DV1F6c9yJO9k8PkZEqBrF2awe8iwc4c7xBw+lDoz5IzuZ4fXetXOOeD XW5ROghAbYM1zOQv2FZiIJBpE+A2JHdbTH0yZXq9CseRXGe5RVTddJcB11sUYtqQmIRKbC dP6YOhQRrnjIYR9XS+C1c++XSFBMJtTyX/P+sAvvWkOooYyGh2Zu9n/i44qF/5m9Ukg+JI oMcUNLnzRAjt3G4oSl63HcB01QF0RW9ZjEFE0T/B61V//D8ebEpWh7YhEqWuX3BzUfGQbm oOxQwMHUQ7HL6gHvh5moDinXkzXzaBiL3N54iTVMtyH4hlh8KX15FYn8cnSL+gHFoV6PA7 CLC333YamaKY2LB6Sbxq8lngDAldV0r/KKB44S9oKzUjbgkaM1pYbPL86i9A X-ME-Proxy: Feedback-ID: i9d664b8f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 2 Aug 2026 21:37:03 -0400 (EDT) From: NeilBrown To: Ian Kent , Chuck Lever , Jake Edge , Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko , Jan Harkes , coda@cs.cmu.edu, Alexander Viro , Christian Brauner , Jan Kara , Trond Myklebust , Anna Schumaker , Amir Goldstein , Andrew Morton , Miklos Szeredi Cc: autofs@vger.kernel.org, linux-kernel@vger.kernel.org, ceph-devel@vger.kernel.org, codalist@coda.cs.cmu.edu, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org Subject: [PATCH v1 01/12] VFS: don't count references through ->d_parent Date: Mon, 3 Aug 2026 11:21:10 +1000 Message-ID: <20260803012648.2195405-2-neilb@ownmail.net> X-Mailer: git-send-email 2.50.0.107.gf914562f5916.dirty In-Reply-To: <20260803012648.2195405-1-neilb@ownmail.net> References: <20260803012648.2195405-1-neilb@ownmail.net> Reply-To: NeilBrown Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: NeilBrown The number of negative child dentries that a given dentry can have is effectively unbounded, so counting the references through ->d_parent can overflow ->d_lockref.count. We only use this count so that we can know when there are no remaining references including from children. However most children appear on the ->d_children list and the few remaining children (inactive DCACHE_DENTRY_CURSORs) only exist in a context were a separate reference is held on the parent. So if we count whether d_children is nonempty (i.e. dget() when it becomes non-empty, dput() when it comes empty) and require children not on ->d_children to have a reference on the parent some other way (which they already do), then ->d_lockref.count will not overflow and we can still know exactly when all references, including through ->d_parent, are gone. __d_move() allows that dentries might not be on any d_children list as is the case for IS_ROOT() dentries. Rather than track when this is the case we dget() either parent if they have an empty d_children before children are moved around, then dput() if they turn out to be empty afterwards. This will increment dentry if it IS_ROOT(), and then decrement it afterwards, and will decrement the refcount on old_parent if its ->d_children becomes empty. To help with this, dput_dlock() is added which warns rather than decrementing to zero (which should never happen). When a DCACHE_CURSOR dentry is added to d_children, it is only ever added "before" or "behind" an existing child, so it will never be the first and so never needs to adjust the refcount on the parent. If it remains on the list until dput() it could be the last child to be removed, in which case normal handling applies in dentry_unlist() (where it has been moved from dentry_kill(). Signed-off-by: NeilBrown --- fs/dcache.c | 40 +++++++++++++++++++++++++++++++++------- include/linux/dcache.h | 17 ++++++++++++++++- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 3e9af9de7074..ae726f3ff0cb 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -670,6 +670,8 @@ static inline void dentry_unlist(struct dentry *dentry) return; } __hlist_del(&dentry->d_sib); + if (hlist_empty(&dentry->d_parent->d_children)) + dentry->d_parent->d_lockref.count--; /* * Cursors can move around the list of children. While we'd been * a normal list member, it didn't matter - ->d_sib.next would've @@ -843,7 +845,7 @@ static struct dentry *dentry_kill(struct dentry *dentry) spin_unlock(&dentry->d_lock); if (likely(can_free)) dentry_free(dentry); - if (parent && --parent->d_lockref.count) { + if (parent && parent->d_lockref.count) { spin_unlock(&parent->d_lock); return NULL; } @@ -1986,7 +1988,9 @@ struct dentry *d_alloc(struct dentry * parent, const = struct qstr *name) * don't need child lock because it is not subject * to concurrency here */ - dentry->d_parent =3D dget_dlock(parent); + dentry->d_parent =3D parent; + if (hlist_empty(&parent->d_children)) + dget_dlock(parent); hlist_add_head(&dentry->d_sib, &parent->d_children); spin_unlock(&parent->d_lock); =20 @@ -2005,7 +2009,7 @@ struct dentry *d_alloc_cursor(struct dentry * parent) struct dentry *dentry =3D d_alloc_anon(parent->d_sb); if (dentry) { dentry->d_flags |=3D DCACHE_DENTRY_CURSOR | DCACHE_NORCU; - dentry->d_parent =3D dget(parent); + dentry->d_parent =3D parent; } return dentry; } @@ -2767,7 +2771,9 @@ struct dentry *d_alloc_parallel(struct dentry *parent, =20 new->d_flags |=3D DCACHE_PAR_LOOKUP; spin_lock(&parent->d_lock); - new->d_parent =3D dget_dlock(parent); + new->d_parent =3D parent; + if (hlist_empty(&parent->d_children)) + dget_dlock(parent); hlist_add_head(&new->d_sib, &parent->d_children); if (parent->d_flags & DCACHE_DISCONNECTED) new->d_flags |=3D DCACHE_DISCONNECTED; @@ -3095,12 +3101,21 @@ static void __d_move(struct dentry *dentry, struct = dentry *target, =20 /* ... and switch them in the tree */ dentry->d_parent =3D target->d_parent; + + /* + * Ensure ref count on parents reflect d_children being non-empty, + * which they almost certainly are. If either end up being empty, + * this is handled below after the moves. + */ + if (hlist_empty(&old_parent->d_children)) + dget_dlock(old_parent); + if (dentry->d_parent !=3D old_parent && + hlist_empty(&dentry->d_parent->d_children)) + dget_dlock(dentry->d_parent); + if (!exchange) { copy_name(dentry, target); target->d_hash.pprev =3D NULL; - dentry->d_parent->d_lockref.count++; - if (dentry !=3D old_parent) /* wasn't IS_ROOT */ - WARN_ON(!--old_parent->d_lockref.count); } else { target->d_parent =3D old_parent; swap_names(dentry, target); @@ -3113,6 +3128,17 @@ static void __d_move(struct dentry *dentry, struct d= entry *target, if (!hlist_unhashed(&dentry->d_sib)) __hlist_del(&dentry->d_sib); hlist_add_head(&dentry->d_sib, &dentry->d_parent->d_children); + + /* + * Adjust parent refcounts if either d_children ended up empty. + * This should only ever be old_parent. + */ + if (hlist_empty(&old_parent->d_children)) + dput_dlock(old_parent); + if (dentry->d_parent !=3D old_parent && + hlist_empty(&dentry->d_parent->d_children)) + dput_dlock(dentry->d_parent); + __d_rehash(dentry); fsnotify_update_flags(dentry); fscrypt_handle_d_move(dentry); diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 4b1ff99608e0..64d64bab16fe 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -324,7 +324,7 @@ extern char *dentry_path(const struct dentry *, char *,= int); /* Allocation counts.. */ =20 /** - * dget_dlock - get a reference to a dentry + * dget_dlock - get a reference to a dentry while locked * @dentry: dentry to get a reference to * * Given a live dentry, increment the reference count and return the dentr= y. @@ -339,6 +339,21 @@ static inline struct dentry *dget_dlock(struct dentry = *dentry) return dentry; } =20 +/** + * dput_dlock - put a reference to a dentry while locked + * @dentry: dentry to get a reference to + * + * Given a live dentry, decrement the reference count and return the dentr= y. + * Caller must hold @dentry->d_lock. The dentry must still have + * a reference after the decrement. This can be used when two + * references are held and one must be dropped. + */ +static inline struct dentry *dput_dlock(struct dentry *dentry) +{ + if (!WARN_ON(dentry->d_lockref.count =3D=3D 0)) + dentry->d_lockref.count--; + return dentry; +} =20 /** * dget - get a reference to a dentry --=20 2.50.0.107.gf914562f5916.dirty From nobody Fri Oct 2 10:08:34 2026 Received: from flow-b6-smtp.messagingengine.com (flow-b6-smtp.messagingengine.com [202.12.124.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 54329234994; Mon, 3 Aug 2026 01:37:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721045; cv=none; b=rRv0xN6oC8CBWvQMnHNRjh7bCaBk5WAYF16QCDGSWef3nxiv/leCC5ly8qfW6Xq6Zj0PMR6OLLgxKJT99QQYSdp0BciaI8DbkRJhwI92qIG04kAFHI++6DYlSCwgdNMzXVMsA2pAZdmLJV0/UcOu0Ttu/MRXWR8rh7hx/8s4vD4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721045; c=relaxed/simple; bh=401i6Z5GG9cTsjdVxnD7qFGHqGrtRGtNTRuNnVOuIbE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dGRvrnk6vkNEmHVJE/14rVPuyNTmLBW7CGnvGcuHYuqUGDOl8N1omeY4SF4pKSQliUe7griJ5qiYszUJOpIKDZbA9cipFqniBY9jjl3zFm+ChTS+hGuHO1Mqx5l9h7FeWHB8ShXRTXiseU4Gfl/K19p06OO//3JhF98khvvRp+0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net; spf=pass smtp.mailfrom=ownmail.net; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b=SFTTrsHR; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=UH2KPqA5; arc=none smtp.client-ip=202.12.124.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ownmail.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b="SFTTrsHR"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="UH2KPqA5" Received: from phl-compute-07.internal (phl-compute-07.internal [10.202.2.47]) by mailflow.stl.internal (Postfix) with ESMTP id 34D2213000F6; Sun, 2 Aug 2026 21:37:23 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-07.internal (MEProxy); Sun, 02 Aug 2026 21:37:23 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ownmail.net; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to; s=fm3; t=1785721043; x=1785728243; bh=KKcnwC8Mb4fIQv7KY/kS1ANG9v3IccJuytYcwXx5Xqo=; b= SFTTrsHRCfjKEuFoG73XY+QWDij4Y+67yvj6WJRZVtP2G52UqifGuZyEh7dNz7m0 MbR2CYvy2+6il5GxxEoYO7LNm5zKenJS9o0S33lYFv59bkJSYHMTwIWWv09ls+rB vd/fcZsA5jIPWYH4HzMT33PvYPgkcJhJKHmskCfiDexwkz2j7z7M+YnMzVsUi8eL Xfw9VrCLNAa17eukch4oeP7RR4giOuLmLTwDfJowAh8MCWXOThj/IWFgSFtRXQ7x VV4DPmXSDxXfUucgvoL7ep11mWt9fQimfP2RR03QfQXtOY0dA+T3WZECx6Y8jbpP +VtQZuqWb84Hxx32QS7gaA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1785721043; x=1785728243; bh=K KcnwC8Mb4fIQv7KY/kS1ANG9v3IccJuytYcwXx5Xqo=; b=UH2KPqA5m/eshrS/o 3cEi/iJCLA2eiWhR4mqGKsMiBhrHbQfe12qw+X0HRN4ZdKrnHGLAartGGHQSO/jh PRqGHHMIKqh+9DQp1Uixzfsrl8Vd8aemMFgkp6CJrjVepmHZ9nMFF0OzMj6A7/2w Rn663aSw2U7SHBVDYfDw0tiiLfdSBFW45+RUlcip7MpbwklfVAN73cUKDdLws7qN PPxxk/6trgjChh80hPQP/H+WDIXMwMMjJyrxPBLc/OInrg/qJJSE81vzDAaUck13 LikM8LWNdBKYV3jrrcwAzp6DXViAEfiK4Vv8/yReWkc84qFylHddj0llojG5RwS5 bX/dg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEu0UNNG3Y5ooWE0RW0hb4az30oOOCqiR21A+NF5dBXRIXwF7e1ZQQcPeI1Y+2g3G 2p5taGZPwiaaM3/xeTLW1FCz9U/vJJJskTdg41lYE8VUiZH3MPaQbRkjgX9sOC9ECG/cTt EsmfJCIwMKXkPJdCSK/JXV+uNx8CZDrRBVBEoFtsVP6zXAB6qeB8/w/DykMlOqIBtf3Btj xISH9DdsaZIjdYArnJRbVHFMU7yzbJxCLAWmCc9hUaSiSdlTAIOT4N2Kv8CS0tgpHV+N+f k8nNXssq6c7SmtuWSNjzKUGklZ3BjLsq0xMUopueJIhR+ZPYvLBJVSK2Tqb5Oui4sXj8gj 6lGUmWKiQq5QWvtujIW75gIJM8qapI3KgTP+zsOJP96YF9urjRaChN7TbSXYgSHFLFLB+o T8Kq0E8oAF9UzHiNVaf18Jy0vkeobxFf8c7zeYcswgmkL4rmV1SjocuhyKy72otqvwtpdW qiEIWC+V+icGKH8CBd30ikuUj1Y1pcR0RtJIFtNWkla5bp1uwbqZKR/fS+GmVoTI2ScrkD vQrc50Ez4FuA97dgnA+0hy36RFezvTI4QN1eUcq6zToe9kIqJDYh2M6bPMNmngtPGOOP0L Zu7rE48zBnsHzVSFEZPytQgqm07VXYDh18IcDCyw9PZqhS2VBwWK6Eppcirg X-ME-Proxy: Feedback-ID: i9d664b8f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 2 Aug 2026 21:37:15 -0400 (EDT) From: NeilBrown To: Ian Kent , Chuck Lever , Jake Edge , Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko , Jan Harkes , coda@cs.cmu.edu, Alexander Viro , Christian Brauner , Jan Kara , Trond Myklebust , Anna Schumaker , Amir Goldstein , Andrew Morton , Miklos Szeredi Cc: autofs@vger.kernel.org, linux-kernel@vger.kernel.org, ceph-devel@vger.kernel.org, codalist@coda.cs.cmu.edu, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org Subject: [PATCH v1 02/12] Add and use d_for_each_positive_child family of iterators Date: Mon, 3 Aug 2026 11:21:11 +1000 Message-ID: <20260803012648.2195405-3-neilb@ownmail.net> X-Mailer: git-send-email 2.50.0.107.gf914562f5916.dirty In-Reply-To: <20260803012648.2195405-1-neilb@ownmail.net> References: <20260803012648.2195405-1-neilb@ownmail.net> Reply-To: NeilBrown Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: NeilBrown Provide iterators for the d_children/d_sib lists. These iterators only report dentries that are positive (though they could be negative by the time they are used). As DCACHE_DENTRY_CURSOR dentries are never positive they are never reported. d_for_each_positive_child() takes the parent lock and sets the iterator to each positive child in turn. d_for_each_positive_child_continue() can continue after an existing dentry, or (when initialised to NULL) behave like d_for_each_positive_child(). This requires that something prevent the start dentry from being moved before d_for_each_positive_child_continue() can take the parent lock - typically ->i_rwsem. The use of scoped_guard() in these macros makes it safe to "break" or "goto" out of the loop - the lock will be dropped in that case. These are then used everywhere outside of dcache.c and libfs.c where d_children/d_sib iteration is needed. coda_flag_children() doesn't need rcu_read_lock() as holding any spinlock prevents an RCU critical section from finishing. nfs_clear_verifier_directory() is changed slightly so the parent lock is dropped and retaken between clearing the verifier on the parent and on all the children. I think this is safe. get_next_postive_dentry() in autofs now holds the parent lock a bit less. The only non-trivial code that is no locked any more is parent =3D p->d_parent This cannot need the lock as autofs doesn't support rename and a ref is held on a descendent of parent, so ->d_parent cannot change. And if it could, the lock wouldn't help. Signed-off-by: NeilBrown --- fs/autofs/expire.c | 11 +------- fs/ceph/mds_client.c | 10 +++----- fs/coda/cache.c | 6 +---- fs/libfs.c | 4 +-- fs/nfs/dir.c | 7 ++--- fs/notify/fsnotify.c | 7 +---- include/linux/dcache.h | 58 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 67 insertions(+), 36 deletions(-) diff --git a/fs/autofs/expire.c b/fs/autofs/expire.c index 5c2d459e1e48..7b0a22629415 100644 --- a/fs/autofs/expire.c +++ b/fs/autofs/expire.c @@ -70,12 +70,9 @@ static int autofs_mount_busy(struct vfsmount *mnt, return status; } =20 -/* p->d_lock held */ static struct dentry *positive_after(struct dentry *p, struct dentry *chil= d) { - child =3D child ? d_next_sibling(child) : d_first_child(p); - - hlist_for_each_entry_from(child, d_sib) { + d_for_each_positive_child_continue(child, p) { spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED); if (simple_positive(child)) { dget_dlock(child); @@ -98,9 +95,7 @@ static struct dentry *get_next_positive_subdir(struct den= try *prev, struct dentry *q; =20 spin_lock(&sbi->lookup_lock); - spin_lock(&root->d_lock); q =3D positive_after(root, prev); - spin_unlock(&root->d_lock); spin_unlock(&sbi->lookup_lock); dput(prev); return q; @@ -119,7 +114,6 @@ static struct dentry *get_next_positive_dentry(struct d= entry *prev, return dget(root); =20 spin_lock(&sbi->lookup_lock); - spin_lock(&p->d_lock); while (1) { struct dentry *parent; =20 @@ -127,12 +121,9 @@ static struct dentry *get_next_positive_dentry(struct = dentry *prev, if (ret || p =3D=3D root) break; parent =3D p->d_parent; - spin_unlock(&p->d_lock); - spin_lock(&parent->d_lock); d =3D p; p =3D parent; } - spin_unlock(&p->d_lock); spin_unlock(&sbi->lookup_lock); dput(prev); return ret; diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 3c692ad02c85..5c4e72c3b110 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2182,14 +2182,10 @@ static bool drop_negative_children(struct dentry *d= entry) if (!d_is_dir(dentry)) goto out; =20 - spin_lock(&dentry->d_lock); - hlist_for_each_entry(child, &dentry->d_children, d_sib) { - if (d_really_is_positive(child)) { - all_negative =3D false; - break; - } + d_for_each_positive_child(child, dentry) { + all_negative =3D false; + break; } - spin_unlock(&dentry->d_lock); =20 if (all_negative) shrink_dcache_parent(dentry); diff --git a/fs/coda/cache.c b/fs/coda/cache.c index 245131296300..dca88d749b86 100644 --- a/fs/coda/cache.c +++ b/fs/coda/cache.c @@ -92,16 +92,12 @@ static void coda_flag_children(struct dentry *parent, i= nt flag) { struct dentry *de; =20 - spin_lock(&parent->d_lock); - rcu_read_lock(); - hlist_for_each_entry(de, &parent->d_children, d_sib) { + d_for_each_positive_child(de, parent) { struct inode *inode =3D d_inode_rcu(de); /* don't know what to do with negative dentries */ if (inode) coda_flag_inode(inode, flag); } - rcu_read_unlock(); - spin_unlock(&parent->d_lock); } =20 void coda_flag_inode_children(struct inode *inode, int flag) diff --git a/fs/libfs.c b/fs/libfs.c index 5a0d276379d1..fc283e0a7c3a 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -768,8 +768,7 @@ int simple_empty(struct dentry *dentry) struct dentry *child; int ret =3D 0; =20 - spin_lock(&dentry->d_lock); - hlist_for_each_entry(child, &dentry->d_children, d_sib) { + d_for_each_positive_child(child, dentry) { spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED); if (simple_positive(child)) { spin_unlock(&child->d_lock); @@ -779,7 +778,6 @@ int simple_empty(struct dentry *dentry) } ret =3D 1; out: - spin_unlock(&dentry->d_lock); return ret; } EXPORT_SYMBOL(simple_empty); diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c7caffb31935..7a7419458c6a 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1492,10 +1492,8 @@ static void nfs_clear_verifier_directory(struct inod= e *dir) =20 spin_lock(&this_parent->d_lock); nfs_unset_verifier_delegated(&this_parent->d_time); - dentry =3D d_first_child(this_parent); - hlist_for_each_entry_from(dentry, d_sib) { - if (unlikely(dentry->d_flags & DCACHE_DENTRY_CURSOR)) - continue; + spin_unlock(&this_parent->d_lock); + d_for_each_positive_child(dentry, this_parent) { inode =3D d_inode_rcu(dentry); if (inode && NFS_PROTO(inode)->have_delegation(inode, FMODE_READ, 0)) @@ -1504,7 +1502,6 @@ static void nfs_clear_verifier_directory(struct inode= *dir) nfs_unset_verifier_delegated(&dentry->d_time); spin_unlock(&dentry->d_lock); } - spin_unlock(&this_parent->d_lock); } =20 /** diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 7e2f330fd283..90a2121fc54a 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -85,16 +85,11 @@ void fsnotify_set_children_dentry_flags(struct inode *i= node) /* run all of the children of the original inode and fix their * d_flags to indicate parental interest (their parent is the * original inode) */ - spin_lock(&alias->d_lock); - hlist_for_each_entry(child, &alias->d_children, d_sib) { - if (!child->d_inode) - continue; - + d_for_each_positive_child(child, alias) { spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED); child->d_flags |=3D DCACHE_FSNOTIFY_PARENT_WATCHED; spin_unlock(&child->d_lock); } - spin_unlock(&alias->d_lock); } spin_unlock(&inode->i_lock); } diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 64d64bab16fe..cabf05e74b1f 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -656,6 +656,64 @@ static inline struct dentry *d_next_sibling(const stru= ct dentry *dentry) return hlist_entry_safe(dentry->d_sib.next, struct dentry, d_sib); } =20 +static inline struct dentry *d_next_positive(struct dentry *child) +{ + do { + child =3D d_next_sibling(child); + } while (child && !d_really_is_positive(child)); + return child; +} + +static inline struct dentry *d_first_positive(const struct dentry *parent, + struct dentry *child) +{ + if (!child) + child =3D d_first_child(parent); + else + child =3D d_next_sibling(child); + if (child && !d_really_is_positive(child)) + child =3D d_next_positive(child); + return child; +} + +/** + * d_for_each_positive_child - iterate over positive children in the dcache + * @child: iterator dentry + * @parent: dentry of parent + * + * Iteratively set @child to each positive child of @parent. + * @parent->d_lock should NOT be held. + * @child may no longer be positive when the caller examines it + * so care is still needed which could involve locking the child + * or using d_inode_rcu() to access the inode. + * + * DCACHE_DENTRY_CURSOR dentries will never be returned, only true children + * which have at some point in the past been positive. + */ +#define d_for_each_positive_child(child, parent) \ + scoped_guard(spinlock, &parent->d_lock) \ + for (child =3D d_first_positive(parent, NULL); child; \ + child =3D d_next_positive(child)) + +/** + * d_for_each_positive_child_continue - iterate over remaining positive ch= ildren + * @child: iterator dentry and starting point. + * @parent: dentry of parent + * + * If @child is %NULL this behaves identically to d_for_each_positive_chil= d(). + * Otherwise @child must be an existing child of %parent and subsequent ch= ildren + * in the d_children list of @parent are returned. + * + * Safely using this requires that something prevents @child from being + * renamed to a different directory before we get the lock. Holding + * i_rwsem on the @parent is sufficient. + * + */ +#define d_for_each_positive_child_continue(child, parent) \ + scoped_guard(spinlock, &parent->d_lock) \ + for (child =3D d_first_positive(parent, child); child; \ + child =3D d_next_positive(child)) + void set_default_d_op(struct super_block *, const struct dentry_operations= *); struct dentry *d_make_persistent(struct dentry *, struct inode *); void d_make_discardable(struct dentry *dentry); --=20 2.50.0.107.gf914562f5916.dirty From nobody Fri Oct 2 10:08:34 2026 Received: from flow-b6-smtp.messagingengine.com (flow-b6-smtp.messagingengine.com [202.12.124.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C006C2F3C3D; Mon, 3 Aug 2026 01:37:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721057; cv=none; b=olrvHGAxW2QpoXj/TgxCG/ZTku5wI1IQVklak9JPUgDeYeZCTv6/syIwTZ1PISD5XRVSZHO1RgSkTtSm5WkMh6CANULkKyfjgZfEJDdLyRv/0nd/ehKWpT9R93kyr0sdGhXiMR+2AeEsoLRzMZT8xZ9p2Flp2sNRwtde4LWGKPE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721057; c=relaxed/simple; bh=kQB5g3PsAkk/0CqlPqpxIvXO6glPP7yQs8FckrM/gls=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ir54W2BdmscaOkZDmOqMhGD1sKSAh7n7xs98P/gT6/SrJ9LXIabKsKDlF0LcqKDPT6p2vPEFz1/9bAwKBZVd5ZGjBvyVXrG1iIks9sNQ/DdRniTWboJ0I2UbsDkKFgU96HSkq+n6EytzUb6NE9dzohZxYnCDRD2Oaur8F16lHKA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net; spf=pass smtp.mailfrom=ownmail.net; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b=Z+jESZR4; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=jhZomt6e; arc=none smtp.client-ip=202.12.124.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ownmail.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b="Z+jESZR4"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="jhZomt6e" Received: from phl-compute-09.internal (phl-compute-09.internal [10.202.2.49]) by mailflow.stl.internal (Postfix) with ESMTP id 7A87913000FB; Sun, 2 Aug 2026 21:37:34 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-09.internal (MEProxy); Sun, 02 Aug 2026 21:37:35 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ownmail.net; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to; s=fm3; t=1785721054; x=1785728254; bh=Nq3sb3Z8XnVxlXvaigbejQMhKoZqWwwX66Lyz55aV3g=; b= Z+jESZR4D6LhXxGPJVHDpV/a+sr/XnnzcPc76JzdxbfAj6lWLNgfNE+si999KbUg J2UWCT22JMmB6B7bBC1FoIYW3c8T55ImUalQ8HvlFF//A2nKGk0qpxTxEm5N7uyS lx/3vJP9ox74z+NLY9IyOCHxUI8BNOhe5i7w1BwmzBr3jm+kl5R47mve2XCXSYJi w2aS+XvNPjF2Pcyymcu3BgAJxddw3WMM0RxViUtVX1foXRiKBfNeuQkyKtEfj46o gRa19RrHeAvSNqTwHMijgdG1hTckzmzkknNv/hIhXNjribuace9LyvnX7+BfVop2 VCh2iaGyNSkmTAl8uqSk1Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1785721054; x=1785728254; bh=N q3sb3Z8XnVxlXvaigbejQMhKoZqWwwX66Lyz55aV3g=; b=jhZomt6eacpPq5qwA /9RJ7Qisp3VMsO+vsySgmDrGvy3bruh0D8YI1lHMHXL2zXoEkp0VEmWbcA6ONPpi WDdHZoHAfZr6SBKmTSlBHFQIIHtzKT78AnRBo6gEJi+wCFwcNGr9L3V71ljZyX9J h+Li6iI9gBxQmjdWuDjYmfsb6S2zviANCGKREcsSEJG0dYFMj/UzoS5G4BOIO7Z7 u9D11KCMEftXbTXBJO9VPvUgwADg7oSXYYX/aXEqIx6+rtK0R7EOZddAAM5sbMZw N4UoIXGMXgO41m7PqL06Ch+nPp+57VW8p7n5zEFv0lfpSz1MtvJRN2F+qRBq+BJ2 6E/Cg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFswjlVGtOMO0DJ/yAygp0kikcHV2WSXHSGnlIkcuf0k9rLUdswY4SNsXMvUWMhfJ kpfPtsQuVQ8vSHADhVm4IRY0nolbqOkRQBDAEaT6PViWtUiGaZ1RuyP3TKdnsto1GxdvO6 EDjVnoxMaix/qwxYa/EnmBrWSMWR71Xsepg0lYJWsNgdazP7uMjE+vSD+hiwoRYUCYwqMd 8UCnzcTzoJOqEB2P0a4xlmt6Vi448YXJsDRRsyN3s901toR6OrLn7/rtKpBURTUpkDqxh0 ISJdNDy7NZx3er7DV1F6c9yJO9k8PkZEqBrF2awe8iwc4c7xBw+lDoz5IzuZ4fXetXOOTs fb4oCIGcLJkybBQ75Y0aurX+8rUn6YbqApLfeGOyTpeUXyZndrL0Wf8o5MC6By8YP5tmcm 4N977+HUB0mtV22Fr2sy0bipMAE7WKKxl4Zh7zqSp12M7EmISj+UNhtE8h2T9/+iJn615s 4B83aPsQJNsK/QLf5yGbPmkcPyGPnjyMjSl5Xk/RcCAuRCEYbNuTL7gP6d3GiQPb/0HMy7 /31QBqczc3dgp3cXKckDbed3v3Cv5YtqdrcAT/Rz77wCgQOpFPvOr6ar9wsE9oQ/P9rC3A 6Q9PMMxLYEr2mBoqoZXbZrr8KTxJJxwa7gckunESEQRhu+rXDFRe8WiIpK1g X-ME-Proxy: Feedback-ID: i9d664b8f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 2 Aug 2026 21:37:26 -0400 (EDT) From: NeilBrown To: Ian Kent , Chuck Lever , Jake Edge , Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko , Jan Harkes , coda@cs.cmu.edu, Alexander Viro , Christian Brauner , Jan Kara , Trond Myklebust , Anna Schumaker , Amir Goldstein , Andrew Morton , Miklos Szeredi Cc: autofs@vger.kernel.org, linux-kernel@vger.kernel.org, ceph-devel@vger.kernel.org, codalist@coda.cs.cmu.edu, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org Subject: [PATCH v1 03/12] fsnotify: don't hold a spin_lock across fsnotify_recalc_mask() calls. Date: Mon, 3 Aug 2026 11:21:12 +1000 Message-ID: <20260803012648.2195405-4-neilb@ownmail.net> X-Mailer: git-send-email 2.50.0.107.gf914562f5916.dirty In-Reply-To: <20260803012648.2195405-1-neilb@ownmail.net> References: <20260803012648.2195405-1-neilb@ownmail.net> Reply-To: NeilBrown Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: NeilBrown fsnotify_recalc_mask() is normally called without any spin_lock held, though fsnotify_group_lock() (a mutex) is often held. However dnotify_recalc_inode_mask() does hold a spin_lock when calling fsnotify_recalc_mask(). This is problematic as fsnotify_recalc_mask() can walk the d_children list which can be long. Holding a spin_lock prevents us from using cond_resched() in that walk. So change dnotify_recalc_inode_mask() to NOT call fsnotify_recalc_mask() but install return a flag indicating if it needs to be called. Callers check this flag and call fsnotify_recalc_mask() after dropping the spin_lock. As part of this, dnotify_handle_event() now only calls dnotify_recalc_inode_mask() once rather than possibly several times during the loop. After this change, the only spin_locks held across the d_children walk are the inodes i_lock and the dentries d_lock. These will be addressed in later patches. Signed-off-by: NeilBrown --- fs/notify/dnotify/dnotify.c | 38 ++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 9fb73bafd41d..7553fe0d7850 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -52,14 +52,15 @@ struct dnotify_mark { }; =20 /* - * When a process starts or stops watching an inode the set of events which - * dnotify cares about for that inode may change. This function runs the - * list of everything receiving dnotify events about this directory and ca= lculates - * the set of all those events. After it updates what dnotify is interest= ed in - * it calls the fsnotify function so it can update the set of all events r= elevant - * to this inode. + * When a process starts or stops watching an inode the set of events + * which dnotify cares about for that inode may change. This function + * runs the list of everything receiving dnotify events about this + * directory and calculates the set of all those events. After it + * updates what dnotify is interested in it returns true if the fsnotify + * function should be called (after dropping the lock) so it can update + * the set of all events relevant to this inode. */ -static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark) +static bool dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark) { __u32 new_mask =3D 0; struct dnotify_struct *dn; @@ -72,10 +73,9 @@ static void dnotify_recalc_inode_mask(struct fsnotify_ma= rk *fsn_mark) for (dn =3D dn_mark->dn; dn !=3D NULL; dn =3D dn->dn_next) new_mask |=3D (dn->dn_mask & ~FS_DN_MULTISHOT); if (fsn_mark->mask =3D=3D new_mask) - return; + return false; fsn_mark->mask =3D new_mask; - - fsnotify_recalc_mask(fsn_mark->connector); + return true; } =20 /* @@ -94,6 +94,7 @@ static int dnotify_handle_event(struct fsnotify_mark *ino= de_mark, u32 mask, struct dnotify_struct *dn; struct dnotify_struct **prev; struct fown_struct *fown; + bool need_recalc =3D false; __u32 test_mask =3D mask & ~FS_EVENT_ON_CHILD; =20 /* not a dir, dnotify doesn't care */ @@ -116,11 +117,15 @@ static int dnotify_handle_event(struct fsnotify_mark = *inode_mark, u32 mask, else { *prev =3D dn->dn_next; kmem_cache_free(dnotify_struct_cache, dn); - dnotify_recalc_inode_mask(inode_mark); + need_recalc =3D true; } } =20 + if (need_recalc) + need_recalc =3D dnotify_recalc_inode_mask(inode_mark); spin_unlock(&inode_mark->lock); + if (need_recalc) + fsnotify_recalc_mask(inode_mark->connector); =20 return 0; } @@ -156,6 +161,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id) struct dnotify_struct **prev; struct inode *inode; bool free =3D false; + bool need_recalc =3D false; =20 inode =3D file_inode(filp); if (!S_ISDIR(inode->i_mode)) @@ -174,13 +180,16 @@ void dnotify_flush(struct file *filp, fl_owner_t id) if ((dn->dn_owner =3D=3D id) && (dn->dn_filp =3D=3D filp)) { *prev =3D dn->dn_next; kmem_cache_free(dnotify_struct_cache, dn); - dnotify_recalc_inode_mask(fsn_mark); + if (dnotify_recalc_inode_mask(fsn_mark)) + need_recalc =3D true; break; } prev =3D &dn->dn_next; } =20 spin_unlock(&fsn_mark->lock); + if (need_recalc) + fsnotify_recalc_mask(fsn_mark->connector); =20 /* nothing else could have found us thanks to the dnotify_groups mark_mutex */ @@ -265,6 +274,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned= int arg) fl_owner_t id =3D current->files; struct file *f =3D NULL; int destroy =3D 0, error =3D 0; + bool need_recalc =3D false; __u32 mask; =20 /* we use these to tell if we need to kfree */ @@ -377,9 +387,11 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigne= d int arg) else if (error =3D=3D -EEXIST) error =3D 0; =20 - dnotify_recalc_inode_mask(fsn_mark); + need_recalc =3D dnotify_recalc_inode_mask(fsn_mark); out: spin_unlock(&fsn_mark->lock); + if (need_recalc) + fsnotify_recalc_mask(fsn_mark->connector); =20 if (destroy) fsnotify_detach_mark(fsn_mark); --=20 2.50.0.107.gf914562f5916.dirty From nobody Fri Oct 2 10:08:34 2026 Received: from flow-b6-smtp.messagingengine.com (flow-b6-smtp.messagingengine.com [202.12.124.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC9572E6CAB; Mon, 3 Aug 2026 01:37:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721068; cv=none; b=jATcI7crWonVvfrGprkV2cuy2VeKCCpiRSqgumpzmYfOs2AaBnTFXTCB1IpXTRmr/JLyVnceXXXBHuMqM8bAmbkmgutZhfI/wata1KPhOol5C0B8SZs7rlbB5by66hMLqJQgECgYP83Rd/7QWESQs2D2wxnVN6NSnaoyzSsjWOw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721068; c=relaxed/simple; bh=rSU6UbsrTcyt3N112Q3EtPGvjxX0a0TDtw8hgko0YDw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fNvmjaV4zOt4FW9TjojvcnNQ0eVMIpx5rBL2P9aIc/dL4vcqbVzpx4x1fcbSdlQiwO9soX9PrAbseKLWjLJuzJeX7w7eyiWnysVbC1yFLVW9idAWLqMNeuzH2jmIbEqq/5AMDz6IxJ+raQzhqI+Qt6CG3sEiu3Tzs3bxQv0HNgY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net; spf=pass smtp.mailfrom=ownmail.net; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b=QM459I+X; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=V8CQvIIv; arc=none smtp.client-ip=202.12.124.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ownmail.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b="QM459I+X"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="V8CQvIIv" Received: from phl-compute-03.internal (phl-compute-03.internal [10.202.2.43]) by mailflow.stl.internal (Postfix) with ESMTP id 83B2C13000FC; Sun, 2 Aug 2026 21:37:45 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-03.internal (MEProxy); Sun, 02 Aug 2026 21:37:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ownmail.net; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to; s=fm3; t=1785721065; x=1785728265; bh=afxw517QIyxjWvT6uJJLabhwFNdUnkpoqoM+3My1Tus=; b= QM459I+XDejUzxea0p/QVfF2/YDkhyvXZYOXiOhfyU0lLBm+MVHygDGdlczO7sQB xGQmT7KwdW0piNEXzxVRlvBUNzMvoYyHxSx0CF04XDs70UHLjU1+4eGxR3Tu4gtc 3AbU9oVir5ZBmLLIK2m1yEB0vxQT3ft2gWdhCpMlFoSWF6sqdGZdEBat6FsWTtlq RlRr+0zD32dPdIByulliHxDgbbyRllVNqLHxJAcWi6TrSsMlaG/jTNWUlh23erBg /AAW1W4dWqhLGQihsQ1cmZWmKHpspqnpa3PBTC0UtEl2oteZdXuqeukl8PSnijDJ o4lZvPf7rQ5Mmx4e0uGtsw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1785721065; x=1785728265; bh=a fxw517QIyxjWvT6uJJLabhwFNdUnkpoqoM+3My1Tus=; b=V8CQvIIvPp8DBMFKx 6k/fMNzUZF73VqbuQqjbu5cNvcSuTg9oadaBIfBhhFjD9/8ZWiQXGlotHaUD1PcL 3r5MauFTXBG9qpqyTNpAh+v+VJ9B/9sGxPDZ45LdUBI7xtUQr75EMB/B5diKZ8ca ShXHb1bnf63cDb43nIlmTpX59xwGyM6dGQjf8VaBpXkmqXfqJc0Mvl5Pc2O1aNHZ YlnAX5T+aM8ZmiSFi0uhMZ2/8FCh5G9SNAA37BVTrUcsvbgN2PRnkX3MBPK14j3F KnV7L6gn2lmweGsiTJe5XMU89yZDGvsHYly7BnnKTX4sJloeb60VuqqdWa3Tds87 700Jw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFswjlVGtOMO0DJ/yAygp0kikcHV2WSXHSGnlIkcuf0k9rLUdswY4SNsXMvUWMhfJ kpfPtsQuVQ8vSHADhVm4IRY0nolbqOkRQBDAEaT6PViWtUiGaZ1RuyP3TKdnsto1GxdvO6 EDjVnoxMaix/qwxYa/EnmBrWSMWR71Xsepg0lYJWsNgdazP7uMjE+vSD+hiwoRYUCYwqMd 8UCnzcTzoJOqEB2P0a4xlmt6Vi448YXJsDRRsyN3s901toR6OrLn7/rtKpBURTUpkDqxh0 ISJdNDy7NZx3er7DV1F6c9yJO9k8PkZEqBrF2awe8iwc4c7xBw+lDoz5IzuZ4fXetXOOIf p3XSqG6UtFEs/BmMHkY3CQfXIvgzw8oapoHNClzH0uYron6Vd63SEIhb8HzP165rHbrwzn kbT2arbSvF+izWEpASygMM17t9hzCbLozecAqfY42LcHUEtXV2+3EedS3fhSEUefNmAVat doeVB8roamWdmH4qhmn6CoykF7m6+Rc5fE2dfnY+sufLLM+1mea+NWTB0uPW7auy8n63nK GpqR8jx6I3iWlTzYcEoAo5PSX0v8AZ3WAOBqGhaf62Mx2rPEJir73bxffr9SMBkdigumGV S98iIp1gH0kX4Vd5JzGBOafOlDfpV+okzj8jajlIfQM8so5MjpOcInCEbreg X-ME-Proxy: Feedback-ID: i9d664b8f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 2 Aug 2026 21:37:37 -0400 (EDT) From: NeilBrown To: Ian Kent , Chuck Lever , Jake Edge , Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko , Jan Harkes , coda@cs.cmu.edu, Alexander Viro , Christian Brauner , Jan Kara , Trond Myklebust , Anna Schumaker , Amir Goldstein , Andrew Morton , Miklos Szeredi Cc: autofs@vger.kernel.org, linux-kernel@vger.kernel.org, ceph-devel@vger.kernel.org, codalist@coda.cs.cmu.edu, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org Subject: [PATCH v1 04/12] fsnotify: reduce i_lock hold time in fsnotify_set_children_dentry_flags() Date: Mon, 3 Aug 2026 11:21:13 +1000 Message-ID: <20260803012648.2195405-5-neilb@ownmail.net> X-Mailer: git-send-email 2.50.0.107.gf914562f5916.dirty In-Reply-To: <20260803012648.2195405-1-neilb@ownmail.net> References: <20260803012648.2195405-1-neilb@ownmail.net> Reply-To: NeilBrown Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: NeilBrown Rather than hold i_lock across a d_children walk, dget() a reference to the dentry and drop the i_lock before the walk. This requires that we dput() which can sleep. Now that no locks are held across calls to fsnotify_set_children_dentry_flags(), this is safe. Signed-off-by: NeilBrown --- fs/notify/fsnotify.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 90a2121fc54a..aa94c0fa7686 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -71,27 +71,32 @@ void fsnotify_sb_free(struct super_block *sb) */ void fsnotify_set_children_dentry_flags(struct inode *inode) { - struct dentry *alias; + struct dentry *alias, *child; =20 if (!S_ISDIR(inode->i_mode)) return; =20 spin_lock(&inode->i_lock); - /* run all of the dentries associated with this inode. Since this is a - * directory, there damn well better only be one item on this list */ - for_each_alias(alias, inode) { - struct dentry *child; - - /* run all of the children of the original inode and fix their - * d_flags to indicate parental interest (their parent is the - * original inode) */ - d_for_each_positive_child(child, alias) { - spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED); - child->d_flags |=3D DCACHE_FSNOTIFY_PARENT_WATCHED; - spin_unlock(&child->d_lock); - } - } + /* Find the dentry for inode - there can only be one */ + for_each_alias(alias, inode) + break; + dget(alias); spin_unlock(&inode->i_lock); + + if (!alias) + return; + + /* + * run all of the children of the original inode and fix their + * d_flags to indicate parental interest (their parent is the + * original inode) + */ + d_for_each_positive_child(child, alias) { + spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED); + child->d_flags |=3D DCACHE_FSNOTIFY_PARENT_WATCHED; + spin_unlock(&child->d_lock); + } + dput(alias); } =20 /* --=20 2.50.0.107.gf914562f5916.dirty From nobody Fri Oct 2 10:08:34 2026 Received: from flow-b6-smtp.messagingengine.com (flow-b6-smtp.messagingengine.com [202.12.124.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EEE95234994; Mon, 3 Aug 2026 01:37:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721079; cv=none; b=FrxsaihHkU9VCCeda4qFxps92A/9cE6U2t+6MSnIHoAEIIvIXyzze4lkm/17CjS+SmpjwaKcxBYnPr5N6iVbhlbCZtSR0RLM+wuV2RYg0bCkjE+SMRthdZQutaFNhAQhS6hDfi/uK5/8YN9SL3wP8lrYJSfB6qjn+J21arD0kC8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721079; c=relaxed/simple; bh=yvoq+derSFn4Ih/ybaF7AWNnX/BuYjoP9FBTtDHfYaY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UCYc0upMek4fbpXcEjonH07BnZSHxfa40+FwnfoDk5tKqn3huQiPut2JnQeHiVI4jD4MC9NSw0nKxCC9ImhJdVSSb6rK2bG/gjnDmsQIlOeJWUkgJbo6QOEA3zqSt24gH/7a15QHoAC0+aoAkE69Ur36bA/vJCWdBunPiR4t4UM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net; spf=pass smtp.mailfrom=ownmail.net; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b=gNBB+Mz/; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=Ow0AKg4w; arc=none smtp.client-ip=202.12.124.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ownmail.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b="gNBB+Mz/"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="Ow0AKg4w" Received: from phl-compute-12.internal (phl-compute-12.internal [10.202.2.52]) by mailflow.stl.internal (Postfix) with ESMTP id B0D4B1300101; Sun, 2 Aug 2026 21:37:56 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-12.internal (MEProxy); Sun, 02 Aug 2026 21:37:57 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ownmail.net; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to; s=fm3; t=1785721076; x=1785728276; bh=LRXjGHlh2+nCnx6IVsF6Rd5nMZtgJdRoJmvfHXGHHCU=; b= gNBB+Mz/+u6/HJXv8Lxe9NUGV0PEJRfaJBZmtEtrDmqkVXbq8sFu/+dnSimt0HeG RaL9omXhpMe+oW5HDF1xnZLxdH5frY5umjz2NwiG1zera27HdsXMQmDBHHfm8RK3 RDY/UIhkXVmgW0Cp8K5kvIvWWJAGwXQwiGxJtOoS10Tr5meoKVMsuZ7NL2J5+TDJ hIyFYZ4dmYFXB+sdOckhooMmcDUghh3bk6F/sE82U2vLDKKnNXPl2QAfYazQKCoN TmjWzYveOOlxv2iOiKXyzhA4N1awCcTTadYSezKQngSSQyGUrnjYiXac+H67Gzl+ pd/CvArM+T5Ul0yL04dCtQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1785721076; x=1785728276; bh=L RXjGHlh2+nCnx6IVsF6Rd5nMZtgJdRoJmvfHXGHHCU=; b=Ow0AKg4w/beSCP1X3 AEK9CAQ99dBsJc83L32r/tymlxAmIvmgHuAn0hJrPls+vxdueIp1M9XYJ5iNjJIk xyqDL3ZsM4uMvo3i3nyvfse+9e9V/c5swyOQYun7u9RjtasPatFXyhgWIPUhTDRx qq0GDhTThV1ui7xTqGJDTKM4JTMw+/80jRie8WJLBOfWRoLgVkvukMiVVSTR1aZi QksJN9IOPa/7+Y+Qx/t6cRTsGaC5XXrY7WWJuH8A3s3TxYk+kSufSt8H8RF1zljv yxt9iFNmlwo3m6rL96bnpAHlfXUEDCJQtD9wwHGrIszMOpuThiX/Ae/0LdJcOk+1 Mi3ZA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEu0UNNG3Y5ooWE0RW0hb4az30oOOCqiR21A+NF5dBXRIXwF7e1ZQQcPeI1Y+2g3G 2p5taGZPwiaaM3/xeTLW1FCz9U/vJJJskTdg41lYE8VUiZH3MPaQbRkjgX9sOC9ECG/cTt EsmfJCIwMKXkPJdCSK/JXV+uNx8CZDrRBVBEoFtsVP6zXAB6qeB8/w/DykMlOqIBtf3Btj xISH9DdsaZIjdYArnJRbVHFMU7yzbJxCLAWmCc9hUaSiSdlTAIOT4N2Kv8CS0tgpHV+N+f k8nNXssq6c7SmtuWSNjzKUGklZ3BjLsq0xMUopueJIhR+ZPYvLBJVSK2Tqb5Oui4sXj8It FV+4BN11kfVmubMl0upk5n+Xcy9uFD9BBSQgJHh5L5DafEWPCIVc7b/B5zL2ZAHElqAXSP Jhpk+s3cl0b4f2bSoH/fcExTmw5QRlNHUV1cD0znwrM9ipFPu1c2ycLFcxmSI2RjOhF02o sq0Wz70PmxEJAJAJizhpsqxB9PvjkAVynOLAubHtIziPzNcwMf29po4n9r+t1MzdkniI85 8Hm3Z29rUN3E0QfbLqwpOIYpvs5P1RQ5MZWltY40h7FFBFS1SGEnChOc0vMBViGG9dRKh0 xNXXmunlKHX18AozUeWuv1IcHDQoJbmr+jdFG5WTavERha0V3DIpf1/qzXPA X-ME-Proxy: Feedback-ID: i9d664b8f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 2 Aug 2026 21:37:48 -0400 (EDT) From: NeilBrown To: Ian Kent , Chuck Lever , Jake Edge , Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko , Jan Harkes , coda@cs.cmu.edu, Alexander Viro , Christian Brauner , Jan Kara , Trond Myklebust , Anna Schumaker , Amir Goldstein , Andrew Morton , Miklos Szeredi Cc: autofs@vger.kernel.org, linux-kernel@vger.kernel.org, ceph-devel@vger.kernel.org, codalist@coda.cs.cmu.edu, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org Subject: [PATCH v1 05/12] libfs: simplify scan_positives() Date: Mon, 3 Aug 2026 11:21:14 +1000 Message-ID: <20260803012648.2195405-6-neilb@ownmail.net> X-Mailer: git-send-email 2.50.0.107.gf914562f5916.dirty In-Reply-To: <20260803012648.2195405-1-neilb@ownmail.net> References: <20260803012648.2195405-1-neilb@ownmail.net> Reply-To: NeilBrown Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: NeilBrown This patch removes explicit use of hlist_node from scan_positives() and callers, and consistently uses struct dentry instead. Previously scan_positives() had two args which were closely related: p and last. If last was not NULL, p was precisely &last->d_sib.next. If last WAS NULL, then p was &cursor->d_parent->d_children.first or &cursor->d_sib.next If, for the final case, we pass 'cursor' as 'last', then we only need 'last' not 'p'. For this to work we must dget(cursor) before passing it, as scan_positives() calls dput() on last. So now to scan from the start, pass NULL, to scan from a particular dentry, pass that dentry. Signed-off-by: NeilBrown --- fs/libfs.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/fs/libfs.c b/fs/libfs.c index fc283e0a7c3a..080ca615593c 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -105,16 +105,18 @@ EXPORT_SYMBOL(dcache_dir_close); * If no such element exists, NULL is returned. */ static struct dentry *scan_positives(struct dentry *cursor, - struct hlist_node **p, - loff_t count, - struct dentry *last) + struct dentry *last, + loff_t count) { struct dentry *dentry =3D cursor->d_parent, *found =3D NULL; + struct dentry *next; =20 spin_lock(&dentry->d_lock); - while (*p) { - struct dentry *d =3D hlist_entry(*p, struct dentry, d_sib); - p =3D &d->d_sib.next; + next =3D last ? d_next_sibling(last) : d_first_child(dentry); + while (next) { + struct dentry *d =3D next; + + next =3D d_next_sibling(next); // we must at least skip cursors, to avoid livelocks if (d->d_flags & DCACHE_DENTRY_CURSOR) continue; @@ -131,10 +133,10 @@ static struct dentry *scan_positives(struct dentry *c= ursor, if (!hlist_unhashed(&cursor->d_sib)) __hlist_del(&cursor->d_sib); hlist_add_behind(&cursor->d_sib, &d->d_sib); - p =3D &cursor->d_sib.next; spin_unlock(&dentry->d_lock); cond_resched(); spin_lock(&dentry->d_lock); + next =3D d_next_sibling(cursor); } } spin_unlock(&dentry->d_lock); @@ -163,8 +165,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offse= t, int whence) inode_lock_shared(dentry->d_inode); =20 if (offset > 2) - to =3D scan_positives(cursor, &dentry->d_children.first, - offset - 2, NULL); + to =3D scan_positives(cursor, NULL, offset - 2); spin_lock(&dentry->d_lock); hlist_del_init(&cursor->d_sib); if (to) @@ -191,23 +192,19 @@ int dcache_readdir(struct file *file, struct dir_cont= ext *ctx) struct dentry *dentry =3D file->f_path.dentry; struct dentry *cursor =3D file->private_data; struct dentry *next =3D NULL; - struct hlist_node **p; =20 if (!dir_emit_dots(file, ctx)) return 0; =20 - if (ctx->pos =3D=3D 2) - p =3D &dentry->d_children.first; - else - p =3D &cursor->d_sib.next; + if (ctx->pos > 2) + next =3D dget(cursor); =20 - while ((next =3D scan_positives(cursor, p, 1, next)) !=3D NULL) { + while ((next =3D scan_positives(cursor, next, 1)) !=3D NULL) { if (!dir_emit(ctx, next->d_name.name, next->d_name.len, d_inode(next)->i_ino, fs_umode_to_dtype(d_inode(next)->i_mode))) break; ctx->pos++; - p =3D &next->d_sib.next; } spin_lock(&dentry->d_lock); hlist_del_init(&cursor->d_sib); --=20 2.50.0.107.gf914562f5916.dirty From nobody Fri Oct 2 10:08:34 2026 Received: from flow-b6-smtp.messagingengine.com (flow-b6-smtp.messagingengine.com [202.12.124.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A1362E62B7; Mon, 3 Aug 2026 01:38:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721090; cv=none; b=WhSEw5jK6g8iRWsUFtqJA+nDeDSlPj8wx9ETEaPXbjCGKK/w5CqdnyMmb/QL9rquGDUD9jJX+dt47AO71qUqf/x7gQG3Qs3FwbxXNBj7ymFdind55w8vmha8czqbQQYMH4MtsUcMoYpsHFUZRq7vmOYSkETPpYR7damfQh52Pr0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721090; c=relaxed/simple; bh=aB5XCh3sI7aPq9H6AooS1XuOPKUD2qGI9YwuJoSTcww=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uCMVG2aneirHIYaam1B/Rs+4laydRD/mtM8yiZBvAUsq2j2a7Ra5sIB56b7wNiI6LppLxiMhl8lDoug1vfYAHrhBb8+bR7PjQiPxNIIHBuCwkesj+VTMveSuIyl2avyggrGqKWo2k/zmqk7l9fYEWK1alRHUJ/8WzkJSR3hNhDY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net; spf=pass smtp.mailfrom=ownmail.net; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b=NfV8h9Is; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=PUiEhnLW; arc=none smtp.client-ip=202.12.124.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ownmail.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b="NfV8h9Is"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="PUiEhnLW" Received: from phl-compute-05.internal (phl-compute-05.internal [10.202.2.45]) by mailflow.stl.internal (Postfix) with ESMTP id CA8F51300104; Sun, 2 Aug 2026 21:38:07 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-05.internal (MEProxy); Sun, 02 Aug 2026 21:38:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ownmail.net; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to; s=fm3; t=1785721087; x=1785728287; bh=GKZh/3B5CaR2ylbw+QK2bTTg4cFoSWL0/KYsAA3wzEQ=; b= NfV8h9IsOaCXlT8oULh0l35P5CvWujiXl3Y0oVKNnmb2/R7EkyOPyQ2m3yVBp+rS 2dxf0pwaZMcUx33ycTlfLY9Vzu1y33jLKok5bJiL4M5Ge8G0kOoyh8gTORGi0e6r v4ElBosy3l+IGSmDCa+ju2LDLAyT9Kt5s/gIb+A3neTwnd+G4O3jutBAWy12hVa5 vzSKWrIgAFIPCjQuRAVUVEs75OIRUtxojDzMgNdNgnvQiK945IFIAOfTfVMe6Hi4 3NclvktRSwl+GSQa766ejuEUn3t+JNSdgNypiHHaAtymu71KrruIo7WRVvcobZb6 IgM1+wO7eTULzEGiM8MWUw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1785721087; x=1785728287; bh=G KZh/3B5CaR2ylbw+QK2bTTg4cFoSWL0/KYsAA3wzEQ=; b=PUiEhnLWws3/Y5ArE NCBjZm8MArowNhlIFt7I82/rMrYH1u2lOUFalCqQNH9oTQwrSHvN+htF1TbU1HQj 9gSWjCct/DCMsGUFWojxQe7+Xa54rVJVC32XwddL4Z+2w5aRJUUixUlpEtGuJH4f d/InlJKnidxhfdDGHGnE+O4aj14cDCn773jhKttg9FO0fYkiT4Pa7sO+Izka0gYu lHxHRde8496pK8I6cLo4O+bRWPZ3k+QGBE6XqMmyKsQJ1R2/k5OclIWVtvnBvMeu NJwqPRxc2SfjBVG4XJ9e6dnaXCEA6gMYXUrY80mRTsatQwxe+JsqnBHyYY+Ekxxg g2YWg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEu0UNNG3Y5ooWE0RW0hb4az30oOOCqiR21A+NF5dBXRIXwF7e1ZQQcPeI1Y+2g3G 2p5taGZPwiaaM3/xeTLW1FCz9U/vJJJskTdg41lYE8VUiZH3MPaQbRkjgX9sOC9ECG/cTt EsmfJCIwMKXkPJdCSK/JXV+uNx8CZDrRBVBEoFtsVP6zXAB6qeB8/w/DykMlOqIBtf3Btj xISH9DdsaZIjdYArnJRbVHFMU7yzbJxCLAWmCc9hUaSiSdlTAIOT4N2Kv8CS0tgpHV+N+f k8nNXssq6c7SmtuWSNjzKUGklZ3BjLsq0xMUopueJIhR+ZPYvLBJVSK2Tqb5Oui4sXj8pa LA+RA8It3pPbvsYOL+YUfdzRtKGoHHWwOx5L4zVveeCdJsXJwkSfFeTY+5F8NrJC5gBxDt WNl0jirfhS19W53+YqUyMEFomX6ldS5Cc2Mt4rDzyRlVO91iX/xoQH66zIH6s7FAyYN5B7 WHRqLUk6XJQMCfTRjSzXQ+7VWJ9A1tdfj63/BnwvzxK3NIAhjUWJip9v99ioHdAEURDGG4 IHZwCMe2vXUALOvG/xejUwMaf7gbfK1U6VS8vgoU6WTnpnCmmXWhHO7NtmthPuRAQiY/Kg dobJf8L9XSRliO3uilUmtZWfWnq0Vh3VMo9uzY5SNP8HsOGrziFp2JGMF59w X-ME-Proxy: Feedback-ID: i9d664b8f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 2 Aug 2026 21:38:00 -0400 (EDT) From: NeilBrown To: Ian Kent , Chuck Lever , Jake Edge , Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko , Jan Harkes , coda@cs.cmu.edu, Alexander Viro , Christian Brauner , Jan Kara , Trond Myklebust , Anna Schumaker , Amir Goldstein , Andrew Morton , Miklos Szeredi Cc: autofs@vger.kernel.org, linux-kernel@vger.kernel.org, ceph-devel@vger.kernel.org, codalist@coda.cs.cmu.edu, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org Subject: [PATCH v1 06/12] libfs: change scan_positives() to use d_for_each_positive_child_continue() Date: Mon, 3 Aug 2026 11:21:15 +1000 Message-ID: <20260803012648.2195405-7-neilb@ownmail.net> X-Mailer: git-send-email 2.50.0.107.gf914562f5916.dirty In-Reply-To: <20260803012648.2195405-1-neilb@ownmail.net> References: <20260803012648.2195405-1-neilb@ownmail.net> Reply-To: NeilBrown Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: NeilBrown Using d_for_each_positive_child_continue() simplifies this code slightly and make is easier to read. Signed-off-by: NeilBrown --- fs/libfs.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/fs/libfs.c b/fs/libfs.c index 080ca615593c..c2369ea9196f 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -109,17 +109,9 @@ static struct dentry *scan_positives(struct dentry *cu= rsor, loff_t count) { struct dentry *dentry =3D cursor->d_parent, *found =3D NULL; - struct dentry *next; + struct dentry *d =3D last; =20 - spin_lock(&dentry->d_lock); - next =3D last ? d_next_sibling(last) : d_first_child(dentry); - while (next) { - struct dentry *d =3D next; - - next =3D d_next_sibling(next); - // we must at least skip cursors, to avoid livelocks - if (d->d_flags & DCACHE_DENTRY_CURSOR) - continue; + d_for_each_positive_child_continue(d, dentry) { if (simple_positive(d) && !--count) { spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); if (simple_positive(d)) @@ -133,13 +125,12 @@ static struct dentry *scan_positives(struct dentry *c= ursor, if (!hlist_unhashed(&cursor->d_sib)) __hlist_del(&cursor->d_sib); hlist_add_behind(&cursor->d_sib, &d->d_sib); + d =3D cursor; spin_unlock(&dentry->d_lock); cond_resched(); spin_lock(&dentry->d_lock); - next =3D d_next_sibling(cursor); } } - spin_unlock(&dentry->d_lock); dput(last); return found; } --=20 2.50.0.107.gf914562f5916.dirty From nobody Fri Oct 2 10:08:34 2026 Received: from flow-b6-smtp.messagingengine.com (flow-b6-smtp.messagingengine.com [202.12.124.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 070142EAB6F; Mon, 3 Aug 2026 01:38:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721101; cv=none; b=NK8g6IjRn7yG6A7Xxq8SnS/N94YA8pUmMg6Q2UdgiSGrEZuTYUyC7sdyFek8PQP1yIyNQ1KeOTS04UryUkY5dY5avbwPafT3+J86stU9ZCAjlMjdvIy7+zn9ConlPRQantKLGGIrxBzfKaUTVAxsDdFiCaBSyT5aEsQriM3bzBQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721101; c=relaxed/simple; bh=2cufU8yvi9RClrUlLLXvb9cfqVLrKy+3OTzuskkAQBk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=b9dJQs340V78B07/1oMO5dajKZnxiK5CEgkEvnU4mtMQ80zxduGm4QbNb+PZOdvj/gFmHIAJmmErgw6SXVAs1BJu9LcafX1rdS7rzA/cyVqfb5pM0gjHsHEsMG6RfKKMjLtaJgaX4rAXh/a7mz4oRftxC2ZjdxLEYt3MeUTAQnA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net; spf=pass smtp.mailfrom=ownmail.net; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b=ST9djPHD; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=N24QlYEm; arc=none smtp.client-ip=202.12.124.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ownmail.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b="ST9djPHD"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="N24QlYEm" Received: from phl-compute-04.internal (phl-compute-04.internal [10.202.2.44]) by mailflow.stl.internal (Postfix) with ESMTP id 037421300107; Sun, 2 Aug 2026 21:38:18 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-04.internal (MEProxy); Sun, 02 Aug 2026 21:38:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ownmail.net; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to; s=fm3; t=1785721098; x=1785728298; bh=wCundvHl8EUp99cshH7SIKdPk3plPH4lsyT7KtputbA=; b= ST9djPHDzh8eHNLZ+kmtRf5xz2AM1vTFMmigPkYOo5c3+y6Lm8OVxUf0BQaNSC9t j+t/zoIEP7NtF5zcEJfONCxmvylyXBL8fC9scxMoABsjCPTgkEI8FSNNgUe8xVvz 1MDmxkyeN9kIAy1t8NHhpwkEhyK17qMc085TyhHjdpRGs/EJ7JLzQYHfe5xQVyRD rseY+fQs+gp7X++zXwjMPg4wUiSh/GcShds/jMnyKHhPCGER75ZIhXDRIo647YIw jXTWQkBFobis26Tth0EyHFDuCu0uxhgbaZmKS/d0uUA70TcgE9a7wNIbvKS0Qm5b Hc5YjXzSRGS+2flL5iq6MA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1785721098; x=1785728298; bh=w CundvHl8EUp99cshH7SIKdPk3plPH4lsyT7KtputbA=; b=N24QlYEmtl04bNLDq Szzi8Ev1eSo9hWQSnBguudAKJhG/CHvPi9Jl/tdj3vFt43MXOK2QcjHC79GmvHwa soGJGMKubTaVRaENetIwEYC/lAUlInp5RQrcFQ7ToKNAnwS90blUB3UQxISMH8Q5 5H4NuWbRsC6NSqWh6UekdRbkxRjUWNfB6t7pFgPrw72Sye0GbH5jEHilfvvVd69l ro8QFXY0NXSbPwcWBInT5cWxNgEo9VqS/8QiJ5RQJqz57A03yg8sludrluK7t5O7 d0yD5xZhbmwkewa2RCutYxoG/vcmnY6+KGVYOLnzvi45Ac2mRXXgi58LrituzRSC a9nWQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFswjlVGtOMO0DJ/yAygp0kikcHV2WSXHSGnlIkcuf0k9rLUdswY4SNsXMvUWMhfJ kpfPtsQuVQ8vSHADhVm4IRY0nolbqOkRQBDAEaT6PViWtUiGaZ1RuyP3TKdnsto1GxdvO6 EDjVnoxMaix/qwxYa/EnmBrWSMWR71Xsepg0lYJWsNgdazP7uMjE+vSD+hiwoRYUCYwqMd 8UCnzcTzoJOqEB2P0a4xlmt6Vi448YXJsDRRsyN3s901toR6OrLn7/rtKpBURTUpkDqxh0 ISJdNDy7NZx3er7DV1F6c9yJO9k8PkZEqBrF2awe8iwc4c7xBw+lDoz5IzuZ4fXetXOOZs fOOcpgH4bfLIMB6lfSWNYIEXPzN2voLEMVehyX/DBMYrFJBkeAsJY/hM3y3eq4V24EeHfE mSreAumr4Wl3f6zX+Z1SnyoR2GJjoTdHJASploR208WaujK1nAz1Z8ykDjFNbN8teGTF1D VX/KnV+gmbkkC5nvswMjFrPvGIA8EJkBEPbBrWEANDVPQx1MC/3YY8s/WN1nW7LEzTBoLp qOFUMHxKw22AgN8XVYyGmwOdhcxMJQLdvKNDZ0d6mxd3UE4n8sg0uKKTaqFubCLu0ntHPY SseGkI2vaFs8rHQhv5xfYt8E/hbrB9AhfzEH5rnEbpthsGN+kHhlhNPtYPIg X-ME-Proxy: Feedback-ID: i9d664b8f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 2 Aug 2026 21:38:11 -0400 (EDT) From: NeilBrown To: Ian Kent , Chuck Lever , Jake Edge , Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko , Jan Harkes , coda@cs.cmu.edu, Alexander Viro , Christian Brauner , Jan Kara , Trond Myklebust , Anna Schumaker , Amir Goldstein , Andrew Morton , Miklos Szeredi Cc: autofs@vger.kernel.org, linux-kernel@vger.kernel.org, ceph-devel@vger.kernel.org, codalist@coda.cs.cmu.edu, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org Subject: [PATCH v1 07/12] libfs: allow scan_positives() to be called without a cursor. Date: Mon, 3 Aug 2026 11:21:16 +1000 Message-ID: <20260803012648.2195405-8-neilb@ownmail.net> X-Mailer: git-send-email 2.50.0.107.gf914562f5916.dirty In-Reply-To: <20260803012648.2195405-1-neilb@ownmail.net> References: <20260803012648.2195405-1-neilb@ownmail.net> Reply-To: NeilBrown Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: NeilBrown Rather than taking parent from cursor, pass it in explicitly. And only cond_sched() if a cursor is available. This will allow scan_positives() to be used in place of find_positive_dentry(). Signed-off-by: NeilBrown --- fs/libfs.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/libfs.c b/fs/libfs.c index c2369ea9196f..260f56863742 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -104,11 +104,12 @@ EXPORT_SYMBOL(dcache_dir_close); * found, dentry is grabbed and returned to caller. * If no such element exists, NULL is returned. */ -static struct dentry *scan_positives(struct dentry *cursor, +static struct dentry *scan_positives(struct dentry *dentry, + struct dentry *cursor, struct dentry *last, loff_t count) { - struct dentry *dentry =3D cursor->d_parent, *found =3D NULL; + struct dentry *found =3D NULL; struct dentry *d =3D last; =20 d_for_each_positive_child_continue(d, dentry) { @@ -121,7 +122,7 @@ static struct dentry *scan_positives(struct dentry *cur= sor, break; count =3D 1; } - if (need_resched()) { + if (cursor && need_resched()) { if (!hlist_unhashed(&cursor->d_sib)) __hlist_del(&cursor->d_sib); hlist_add_behind(&cursor->d_sib, &d->d_sib); @@ -156,7 +157,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offse= t, int whence) inode_lock_shared(dentry->d_inode); =20 if (offset > 2) - to =3D scan_positives(cursor, NULL, offset - 2); + to =3D scan_positives(dentry, cursor, NULL, offset - 2); spin_lock(&dentry->d_lock); hlist_del_init(&cursor->d_sib); if (to) @@ -190,7 +191,7 @@ int dcache_readdir(struct file *file, struct dir_contex= t *ctx) if (ctx->pos > 2) next =3D dget(cursor); =20 - while ((next =3D scan_positives(cursor, next, 1)) !=3D NULL) { + while ((next =3D scan_positives(dentry, cursor, next, 1)) !=3D NULL) { if (!dir_emit(ctx, next->d_name.name, next->d_name.len, d_inode(next)->i_ino, fs_umode_to_dtype(d_inode(next)->i_mode))) --=20 2.50.0.107.gf914562f5916.dirty From nobody Fri Oct 2 10:08:34 2026 Received: from flow-b6-smtp.messagingengine.com (flow-b6-smtp.messagingengine.com [202.12.124.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 80BB6234994; Mon, 3 Aug 2026 01:38:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721112; cv=none; b=AI94oDPDamSv2oJBhNAnFNnLqW9rfMbjm/hpgu8XKepyiSusv7xnyFf0mTlH25erkfjSbPPF6FlThfpMfIUUR35WwXZ9SKqjTolWkLjq+8EJJGKyW3zNl/H54K4NdcMRXQ82n91Q6M87SbCzBCdbIhD+bzH/pCZk5JVo4fG3VFA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721112; c=relaxed/simple; bh=abwJDLnaCl8gUqs8UAbpVAsHe0p+acH/jodii6vvHPs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BhlDLGzrOZU0rWSFuPZO6urOIbKI9ITS6n8sSDF/tcbEvkLDFpFFSNRB2fwN/4AlduifGHakviXLndvOnQAw7AM6HVP2O+3sb3kKrSZEl8GD6Yg+8SUVUs010aSKtuwj7dw3A8twuVGs26BMA4xEBtPU4QE1q1WDM1pZkTTJ+wY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net; spf=pass smtp.mailfrom=ownmail.net; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b=LXv/amUy; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=lFIJh9nS; arc=none smtp.client-ip=202.12.124.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ownmail.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b="LXv/amUy"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="lFIJh9nS" Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42]) by mailflow.stl.internal (Postfix) with ESMTP id 498E0130010C; Sun, 2 Aug 2026 21:38:30 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-02.internal (MEProxy); Sun, 02 Aug 2026 21:38:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ownmail.net; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to; s=fm3; t=1785721110; x=1785728310; bh=31JtnpcYZd4fsPZ94hZjJrOdT1mohnvAR1GVbqnnzZE=; b= LXv/amUyruIWD5YRtJNQ+u8/ikBBOH55JsdAqKlhJsDoCG3VXkPJQj3nHJmhBU+B 9ig7ynSr2OJMPVMF86fdJ84EWFtglhCWftTeoA8Nbmp2jYrj4BhWhVyAHpImxUlf X8HMfRafgUadyAEoKZsQOgaBnHbaHykj6S69pYE5XDUZhlfXc98FnjIhwhUOMVQs TE9Q0On+K9DcqWUkiESG2hhQWUjxmXRKLV1NT/Ua0O42S6Zg3/iC3yYJu7XUhYxv xv9ssWMktM7uRFcF+YnwXoQVcgK15v5F7HxRTC0J+ORsWWjAPHFrBEUd+aEjGZwH 0tNoaeZIixJziOJoFh5ibQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1785721110; x=1785728310; bh=3 1JtnpcYZd4fsPZ94hZjJrOdT1mohnvAR1GVbqnnzZE=; b=lFIJh9nSNN6QWA4Yw v7jNnKIaay4DdVAZqUlHrM9IgjL0DyrWnx4l7FV5zevU6h3Kkj70Tnw0Q5nZSRqn YxRnuFxhSLiFJYSZoaIaPg2hBKjXbY0o1GdrK8FJhupzMWyzwcKDpEV03z5k2di9 53TrP8Rlhgu7VU41dz1NsI1aTnzvIAySFkMOhOJMLJz8snxKZr8TdqEuHEeWv6kJ 162XL6xDNP1i2WBsm5QKBpHnQBqPD+eV5PqIP5RIllnWeK93xRvcmMKJTVdRtIna nvvaPnm6v76IizWzAGKSXLazZNc6XOKQ0zeAU3DTCKZbkzuUUO4oiCyB13BOwPoU gfjlA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFswjlVGtOMO0DJ/yAygp0kikcHV2WSXHSGnlIkcuf0k9rLUdswY4SNsXMvUWMhfJ kpfPtsQuVQ8vSHADhVm4IRY0nolbqOkRQBDAEaT6PViWtUiGaZ1RuyP3TKdnsto1GxdvO6 EDjVnoxMaix/qwxYa/EnmBrWSMWR71Xsepg0lYJWsNgdazP7uMjE+vSD+hiwoRYUCYwqMd 8UCnzcTzoJOqEB2P0a4xlmt6Vi448YXJsDRRsyN3s901toR6OrLn7/rtKpBURTUpkDqxh0 ISJdNDy7NZx3er7DV1F6c9yJO9k8PkZEqBrF2awe8iwc4c7xBw+lDoz5IzuZ4fXetXOOYO d0TuZyYFDkUdlU/167fU6rLQ0XBnvJBQ+tdUWsoWVaxciR0e3eqm9HJiRyRFtrqkYYdMhJ tkB4gIy/paGwaxvydaAPU5GL6X7A8uhYQpUBjU1LyKn+3qy7u596xwMDK/44LWGghfs+Dz lZUS7UEf2JbZz6+0/YZdDoMtjFJ7mgbYo9GL011Aa7cJXO222GKJj2lL95was32WrMKCFA ukEeQwABzklkGvKmgOifr91AJUVscQDoyi5P6axmFaQclD5l7FewqQAnlHtVINw1bZWjzp xdsYXdwOFhwI4qUiCS/cs2YU0MqCt1+QAMKD13oTh/pQLh9+vZGE6QvoJAng X-ME-Proxy: Feedback-ID: i9d664b8f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 2 Aug 2026 21:38:22 -0400 (EDT) From: NeilBrown To: Ian Kent , Chuck Lever , Jake Edge , Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko , Jan Harkes , coda@cs.cmu.edu, Alexander Viro , Christian Brauner , Jan Kara , Trond Myklebust , Anna Schumaker , Amir Goldstein , Andrew Morton , Miklos Szeredi Cc: autofs@vger.kernel.org, linux-kernel@vger.kernel.org, ceph-devel@vger.kernel.org, codalist@coda.cs.cmu.edu, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org Subject: [PATCH v1 08/12] libfs: replace find_positive_dentry() with scan_positives() Date: Mon, 3 Aug 2026 11:21:17 +1000 Message-ID: <20260803012648.2195405-9-neilb@ownmail.net> X-Mailer: git-send-email 2.50.0.107.gf914562f5916.dirty In-Reply-To: <20260803012648.2195405-1-neilb@ownmail.net> References: <20260803012648.2195405-1-neilb@ownmail.net> Reply-To: NeilBrown Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: NeilBrown scan_positives() can be used in place of find_positive_dentry(). This makes offset_iterate_dir() simpler as 'next' is no longer needed. offset_dir_lookup() needs an extra loop to find a child on which a ref can be taken, as scan_positives() requires a dentry with a ref. I think this makes a cleaner separation as the RCU read lock no longer needs to be held over the scan call. This will be important in a future patch. Using scan_positives() means, after the next patch, that cursors can appear on the d_sib list, so when finding a dentry from the offset, which might be dead by now (dentry_kill()) we need to step over any cursors to find something we can take a reference on. This requires parent->d_lock as cursors are not RCU-safe. We add lockref_get_not_dead_nested() so that we can opportunistically get a ref on a child while holding the lock on the parent. Signed-off-by: NeilBrown --- fs/libfs.c | 58 ++++++++++++++++------------------------- include/linux/lockref.h | 12 ++++++++- lib/lockref.c | 10 ++++--- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/fs/libfs.c b/fs/libfs.c index 260f56863742..c0771e8b645c 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -435,47 +435,39 @@ static loff_t offset_dir_llseek(struct file *file, lo= ff_t offset, int whence) return vfs_setpos(file, offset, LONG_MAX); } =20 -static struct dentry *find_positive_dentry(struct dentry *parent, - struct dentry *dentry, - bool next) -{ - struct dentry *found =3D NULL; - - spin_lock(&parent->d_lock); - if (next) - dentry =3D d_next_sibling(dentry); - else if (!dentry) - dentry =3D d_first_child(parent); - hlist_for_each_entry_from(dentry, d_sib) { - if (!simple_positive(dentry)) - continue; - spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); - if (simple_positive(dentry)) - found =3D dget_dlock(dentry); - spin_unlock(&dentry->d_lock); - if (likely(found)) - break; - } - spin_unlock(&parent->d_lock); - return found; -} - static noinline_for_stack struct dentry * offset_dir_lookup(struct dentry *parent, loff_t offset) { struct inode *inode =3D d_inode(parent); struct offset_ctx *octx =3D inode->i_op->get_offset_ctx(inode); - struct dentry *child, *found =3D NULL; + struct dentry *found =3D NULL; =20 MA_STATE(mas, &octx->mt, offset, offset); =20 if (offset =3D=3D DIR_OFFSET_FIRST) - found =3D find_positive_dentry(parent, NULL, false); + found =3D scan_positives(parent, NULL, NULL, 1); else { rcu_read_lock(); - child =3D mas_find_rev(&mas, DIR_OFFSET_MIN); - found =3D find_positive_dentry(parent, child, false); + spin_lock(&parent->d_lock); + found =3D mas_find_rev(&mas, DIR_OFFSET_MIN); + if (found) { + /* + * parent lock ensures found is still on + * the d_sib list, but it could be have been marked dead. + * So we need to find something we can get a ref on, + * which isn't a cursor. + */ + hlist_for_each_entry_from(found, d_sib) { + if (!(found->d_flags & DCACHE_DENTRY_CURSOR) && + lockref_get_not_dead_nested(&found->d_lockref, + DENTRY_D_LOCK_NESTED)) + break; + } + } + spin_unlock(&parent->d_lock); rcu_read_unlock(); + if (found && !simple_positive(found)) + found =3D scan_positives(parent, NULL, found, 1); } return found; } @@ -497,18 +489,14 @@ static void offset_iterate_dir(struct file *file, str= uct dir_context *ctx) if (!dentry) goto out_eod; while (true) { - struct dentry *next; - ctx->pos =3D dentry2offset(dentry); if (!offset_dir_emit(ctx, dentry)) break; =20 - next =3D find_positive_dentry(dir, dentry, true); - dput(dentry); + dentry =3D scan_positives(dir, NULL, dentry, 1); =20 - if (!next) + if (!dentry) goto out_eod; - dentry =3D next; } dput(dentry); return; diff --git a/include/linux/lockref.h b/include/linux/lockref.h index 6ded24cdb4a8..9da4fbc2cd13 100644 --- a/include/linux/lockref.h +++ b/include/linux/lockref.h @@ -52,7 +52,17 @@ bool lockref_get_not_zero(struct lockref *lockref); bool lockref_put_or_lock(struct lockref *lockref) __cond_acquires(false, &= lockref->lock); =20 void lockref_mark_dead(struct lockref *lockref); -bool lockref_get_not_dead(struct lockref *lockref); +bool lockref_get_not_dead_nested(struct lockref *lockref, int subclass); +/** + * lockref_get_not_dead - Increments count unless the ref is dead + * @lockref: pointer to lockref structure + * + * Return: 1 if count updated successfully or 0 if lockref was dead + */ +static inline bool lockref_get_not_dead(struct lockref *lockref) +{ + return lockref_get_not_dead_nested(lockref, 0); +} =20 /* Must be called under spinlock for reliable results */ static inline bool __lockref_is_dead(const struct lockref *l) diff --git a/lib/lockref.c b/lib/lockref.c index 5d8e3ef3860e..dddd26100a51 100644 --- a/lib/lockref.c +++ b/lib/lockref.c @@ -136,11 +136,13 @@ void lockref_mark_dead(struct lockref *lockref) EXPORT_SYMBOL(lockref_mark_dead); =20 /** - * lockref_get_not_dead - Increments count unless the ref is dead + * lockref_get_not_dead_nested - Increments count unless the ref is dead * @lockref: pointer to lockref structure + * @subclass: lockdep class for taking ->lock + * * Return: 1 if count updated successfully or 0 if lockref was dead */ -bool lockref_get_not_dead(struct lockref *lockref) +bool lockref_get_not_dead_nested(struct lockref *lockref, int subclass) { bool retval =3D false; =20 @@ -152,7 +154,7 @@ bool lockref_get_not_dead(struct lockref *lockref) return true; ); =20 - spin_lock(&lockref->lock); + spin_lock_nested(&lockref->lock, subclass); if (lockref->count >=3D 0) { lockref->count++; retval =3D true; @@ -160,4 +162,4 @@ bool lockref_get_not_dead(struct lockref *lockref) spin_unlock(&lockref->lock); return retval; } -EXPORT_SYMBOL(lockref_get_not_dead); +EXPORT_SYMBOL(lockref_get_not_dead_nested); --=20 2.50.0.107.gf914562f5916.dirty From nobody Fri Oct 2 10:08:34 2026 Received: from flow-b6-smtp.messagingengine.com (flow-b6-smtp.messagingengine.com [202.12.124.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6824D2E62B7; Mon, 3 Aug 2026 01:38:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721123; cv=none; b=eDmWfPrfJC031hpc3k29V+3LEneUq7dA1dKfe3gdJ+inqgaAuKawXKgnijWyRZvpN9KQM+rs1ulIjCtL1I6W/BUtmzbyBJXuMPuyKjJhKN2/eT4pBs9AbtFAYB/d13bv9rN8o4NNT2vuqE7ZgnX39lLWZ9gNIUs1xkwjmyJK814= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721123; c=relaxed/simple; bh=+3Idv6bxMqOnuq3JEZvBj1oxzFVrITpJmZ12zRTky1k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=F3CS9/trJ4i4pSon5n/4anJH7MaRqTP+n1v7LbeRa/gdIKWXJExRZD6+PWz3Ox4H3HD718VxxRvQ+fKkdBI4w0Hmcc+bTGswxhTaHa1lfepnzlbfeQuOTRvpiWO/gkhZIrnIFjNd0pdALx+22RnBSYnWv0NWRj8rLUGPl/VsamQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net; spf=pass smtp.mailfrom=ownmail.net; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b=gZlZu9WJ; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=jYR2Tw1c; arc=none smtp.client-ip=202.12.124.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ownmail.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b="gZlZu9WJ"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="jYR2Tw1c" Received: from phl-compute-04.internal (phl-compute-04.internal [10.202.2.44]) by mailflow.stl.internal (Postfix) with ESMTP id 369A71300113; Sun, 2 Aug 2026 21:38:41 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-04.internal (MEProxy); Sun, 02 Aug 2026 21:38:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ownmail.net; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to; s=fm3; t=1785721121; x=1785728321; bh=+K59W8wegJRgf4rZVwaCEzIeJ3KAOgf2KEvJDu7Itzk=; b= gZlZu9WJFcmlVE8++0HlLN20+XcGxLuoITGWEGggLbzuvwtNr0gvdCgGVjl6giJS fIOGnzZ+3TKKA3jN7cvLDt1hDF66dxhmhGLmUeOEW2a2+2IIOIt9ID3/638fEN2I qq3Tz+cZQHfF4WhNBP/v1GXBXT3RtWuA2P44oR5zI+aSnceOtjSyEW3LLtN2FXrb Fl4dxAcIG1LFzXkgG07la2gMZglENBn21/9tfhqg07oZ0F8GVzs4Lrjt0rMqXdsL sZzM5MtoqD1xO+9aW5ueAAgwGt3Q8X9VpDf0I2rE5RQUIXEClyOL8t8UQHzYg36I Y/ebO+k+07kU6F+QWlEi+g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1785721121; x=1785728321; bh=+ K59W8wegJRgf4rZVwaCEzIeJ3KAOgf2KEvJDu7Itzk=; b=jYR2Tw1chu2Z0fefB yE8Mso7Z/uBk1feSgvruMx1Qvqeh31Q5SrsY5otL2nHQkQ4+ctY6JORdipbjBx0J VFmXjQXXHwuK3i5EpOkcbuRGph21EGcbpYOBM8d3WUuffbp1HGgVIJQmQG6aUoI0 hu1QqPLqBeESrTmyXTKpciz1x1QUQBCGKCmtXDrmrR/X+SPVyLJA1aRmcTUubepf hOoDCugXdSGASotH+Q+UZVTHPYGmI2ZJ8uYKKwlfLupW5Znp7coBKRMpRUgiqPxN AGa8j5MkgPTLOhwjo8thjn6PpWg0lNTdnn0/AL36ZhW3qnKK+31SXrYzHnlWV9B3 oE8Jg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEkjpQitAtmxGBQYKqyuxI2Zkeo3c6RoaKCNErqeb7OpTUkwok+umPK8wjjzKilLR oEkJ4cvJVGjSJ84RQAU1yMp4OnVAa0j48I+IZh9Fdm8T9NlXb22vW2b++I/w1xpR0D9cGg PY5vxXMwbazIrQndnHZZeUaDjtiO7oMO4JfvURQOW8xpTRIAhWmk/yj3tGiTCFDkK11PUi 8zP+PAM6p9S6yYk+YxJK09JqJLxfofUFwglAMcxid0fjJ/8eCuMBF6ZgJ9khwYNTvmmvDv XHb98vv+s9pbhqVhgG7tjgoBPJWqvJT0PbLNRH63wXqa3Yd9frMtJBXjxnj2koyaKciEdI bRbRUQ3euKwQRaJmomeMioKgyg03Gsf8sWYRPARCdg9ZmzReBQTpAcs29YeE1w7xi/MfQr 8P+nRgrFcRmwZgGIQrovzK3fawYO5NRUJEpbBA2+n9kl8fnyOsy0rz1efQypHE+Hhp4WW9 bc0XlBZi78SpfbzaqVsMsJB2YrdputGlmucUr34SmSbnDXU42O53QE4FatftoKdy/JWkvu /vuv+V+QvXf07yHfzDknLcfnGrVoa8lIhgyL6tuG8J59arzxB796XURKGnl/mUyMU6vyb7 jVMmGLbjidEC7RaL7MFpOiAlD4kZRfYhQemaKB17A/y6yQbi+uaXO6Kw1wYQ X-ME-Proxy: Feedback-ID: i9d664b8f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 2 Aug 2026 21:38:33 -0400 (EDT) From: NeilBrown To: Ian Kent , Chuck Lever , Jake Edge , Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko , Jan Harkes , coda@cs.cmu.edu, Alexander Viro , Christian Brauner , Jan Kara , Trond Myklebust , Anna Schumaker , Amir Goldstein , Andrew Morton , Miklos Szeredi Cc: autofs@vger.kernel.org, linux-kernel@vger.kernel.org, ceph-devel@vger.kernel.org, codalist@coda.cs.cmu.edu, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org Subject: [PATCH v1 09/12] autofs: don't hold ->lookup_lock in get_next_positive_* Date: Mon, 3 Aug 2026 11:21:18 +1000 Message-ID: <20260803012648.2195405-10-neilb@ownmail.net> X-Mailer: git-send-email 2.50.0.107.gf914562f5916.dirty In-Reply-To: <20260803012648.2195405-1-neilb@ownmail.net> References: <20260803012648.2195405-1-neilb@ownmail.net> Reply-To: NeilBrown Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: NeilBrown get_next_positive_subdir() and get_next_positive_dentry() currently hold ->lookup_lock while walking the d_children list, which a subsequent patch will add schedule points to. So this spinlock will be a problem. The only data structures that a protected by ->lookup_lock are the sbi->expiring and sbi->active_list lists of inodes. Neither of these are accessed in these functions, so the lock cannot be needed. Signed-Off-By: NeilBrown --- fs/autofs/expire.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/autofs/expire.c b/fs/autofs/expire.c index 7b0a22629415..704d5394cbb8 100644 --- a/fs/autofs/expire.c +++ b/fs/autofs/expire.c @@ -91,12 +91,9 @@ static struct dentry *positive_after(struct dentry *p, s= truct dentry *child) static struct dentry *get_next_positive_subdir(struct dentry *prev, struct dentry *root) { - struct autofs_sb_info *sbi =3D autofs_sbi(root->d_sb); struct dentry *q; =20 - spin_lock(&sbi->lookup_lock); q =3D positive_after(root, prev); - spin_unlock(&sbi->lookup_lock); dput(prev); return q; } @@ -107,13 +104,11 @@ static struct dentry *get_next_positive_subdir(struct= dentry *prev, static struct dentry *get_next_positive_dentry(struct dentry *prev, struct dentry *root) { - struct autofs_sb_info *sbi =3D autofs_sbi(root->d_sb); struct dentry *p =3D prev, *ret =3D NULL, *d =3D NULL; =20 if (prev =3D=3D NULL) return dget(root); =20 - spin_lock(&sbi->lookup_lock); while (1) { struct dentry *parent; =20 @@ -124,7 +119,6 @@ static struct dentry *get_next_positive_dentry(struct d= entry *prev, d =3D p; p =3D parent; } - spin_unlock(&sbi->lookup_lock); dput(prev); return ret; } --=20 2.50.0.107.gf914562f5916.dirty From nobody Fri Oct 2 10:08:34 2026 Received: from flow-b6-smtp.messagingengine.com (flow-b6-smtp.messagingengine.com [202.12.124.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C33C234994; Mon, 3 Aug 2026 01:38:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721135; cv=none; b=g6eI1o7Ul9d/Vqm3RMhpTF0IXGqZQV8vak7bj2iAqZCozItbf2esyp+qP1ApqyzcBwL6IDHqLBqE6vox6E63sS66nFToQMYRBg4LJDefobscYBl3WFx9AtMdfGKkZ6V2SHIDvAE4yVpoYemdzHru6CyHUMI2ufQXqtglTUzcIok= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721135; c=relaxed/simple; bh=fMDmOL5xr70ejVzd98YeW55n7qvQlOtD8K5j6TVKERA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MA54xIVI5wI+S4zGx+KghArFnbyd2TUgFqRYPvyn/UTTlIFn04dJDS9BF88A5GAG940pgkIfsqk4bGkHplzxrdCDlivuBiaeT/BafgHo8B8i/n6i4fghoULRB+9bQL3w1oGb6Pg2eQb1zVhoJejLtOLLP3f58mN8mwLZ/nuF0Vg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net; spf=pass smtp.mailfrom=ownmail.net; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b=Bg8FIFon; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=kRCj3OpC; arc=none smtp.client-ip=202.12.124.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ownmail.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b="Bg8FIFon"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="kRCj3OpC" Received: from phl-compute-03.internal (phl-compute-03.internal [10.202.2.43]) by mailflow.stl.internal (Postfix) with ESMTP id 2946D130010E; Sun, 2 Aug 2026 21:38:53 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-03.internal (MEProxy); Sun, 02 Aug 2026 21:38:53 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ownmail.net; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to; s=fm3; t=1785721132; x=1785728332; bh=dqe2sIc1xWOg8fDRLcGbXPyHqmKKgfQNRiIuqbpB9V4=; b= Bg8FIFon7MAwRmBNMICJrr7ehcG+hdMYC641d0f622chaUMbePhjTSpeBVjp8J5W 5sx0RRtLTaPDwOpuJE5A652fDki/K/Ax8Dk5z734jYNdPamOPlwi+d74BlFPKX0e fX9QaUT6BFFtunrQRHaP/vyJXtRp5YqhlxXrEqR9BeIyPev95siMFoLn3DQpFp7q SnhE8haoh7k3VzSpSQuNzOQMnTX/H7lT7XRfIywTj6pA724PIe9MQwHnXEkM4TYp fpdfAo+eS02OqVUZWfZm6HQdd3Ee1ck6iTEJBDyAbkexoyo5XPabi6wJx6y4OnOU r4jCXmhZN5zxU3iXFpYt8w== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1785721132; x=1785728332; bh=d qe2sIc1xWOg8fDRLcGbXPyHqmKKgfQNRiIuqbpB9V4=; b=kRCj3OpCccEdYbWW1 IYKQVpiq8uJbILnzneD5zHiyvGFZ5VOA1fbDlC7fKinrzKSslgfrZhc4RRzeN6DA fDbb0hc4//dwroeejP28czRGd9Td/RhQaWxTuTd6RN98UbtVxpE/E4eBV+KfRFyT fcQ8JaOn65N5wOd2cc9Hb5VGQ/Dx4G6tImwjljq40mSjO35hX9JjBg5V5O+p95I3 ulCZys9gkrxPIF67qiu9pB8qjBn6Ko40B7ICBi9Oq13JJ8dkkPRkYdsUjk9dZ/T9 1t72tTFhsfd5eOiJMfXnLz7pWuSW06kYrOO8J3ss1TnPstDUPCbidMekLLbUrluA QrcuQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEkjpQitAtmxGBQYKqyuxI2Zkeo3c6RoaKCNErqeb7OpTUkwok+umPK8wjjzKilLR oEkJ4cvJVGjSJ84RQAU1yMp4OnVAa0j48I+IZh9Fdm8T9NlXb22vW2b++I/w1xpR0D9cGg PY5vxXMwbazIrQndnHZZeUaDjtiO7oMO4JfvURQOW8xpTRIAhWmk/yj3tGiTCFDkK11PUi 8zP+PAM6p9S6yYk+YxJK09JqJLxfofUFwglAMcxid0fjJ/8eCuMBF6ZgJ9khwYNTvmmvDv XHb98vv+s9pbhqVhgG7tjgoBPJWqvJT0PbLNRH63wXqa3Yd9frMtJBXjxnj2koyaKciERh rafP46XaITFdo9pKORYOnglDgqr99OWqYHwEW+SMlN/9n+R11fdLsQc1SOZwkrwBe94m9T 8y2gquTzLzzaGbD5pYA7ab6rBeC5Ty4jLkt9jaOk9Y8dh/sW99A/dopErSZLPsZF210s1F 3oDmXkUwJCZpbe84U/4euGrq0liM0Fdi4WehI7MDXx/7dGNWEG3eCd0tWtI9EQMWutUiqv 8U6fLQioOjwOxBh8raxYln08HNwi30/xTsXiqSQb7UmqR7qCmPHOpckhY02VjSqBLhu0KZ sJ8erdRovl2o4STqxXjsWqp7gCGeBKfnLiafsxBlloitYzs82DI3flHdIteQ X-ME-Proxy: Feedback-ID: i9d664b8f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 2 Aug 2026 21:38:44 -0400 (EDT) From: NeilBrown To: Ian Kent , Chuck Lever , Jake Edge , Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko , Jan Harkes , coda@cs.cmu.edu, Alexander Viro , Christian Brauner , Jan Kara , Trond Myklebust , Anna Schumaker , Amir Goldstein , Andrew Morton , Miklos Szeredi Cc: autofs@vger.kernel.org, linux-kernel@vger.kernel.org, ceph-devel@vger.kernel.org, codalist@coda.cs.cmu.edu, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org Subject: [PATCH v1 10/12] VFS: don't move dentries in d_sib list when they have the same parent Date: Mon, 3 Aug 2026 11:21:19 +1000 Message-ID: <20260803012648.2195405-11-neilb@ownmail.net> X-Mailer: git-send-email 2.50.0.107.gf914562f5916.dirty In-Reply-To: <20260803012648.2195405-1-neilb@ownmail.net> References: <20260803012648.2195405-1-neilb@ownmail.net> Reply-To: NeilBrown Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: NeilBrown When __d_move() moves or exchanges dentries it currently always moves both dentries to the head of the ->d_children list of the respective parents. When they have the same parent, this simply moves them from where they are to the start in the same list. So it achieves nothing. A future patch will allow d_for_each_positive_child() to drop and retake the parent's d_lock during the iteration. With the current __d_move behaviour this would allow a dentry to be moved to the front and so missed, even though it is still in the same directory. This might be unexpected. With this change a the only dentries that d_for_each_positive_child() might miss are those moved out of the directory, or those moved in after the iteration started. These are unavoidable and should not be unexpected. Signed-off-by: NeilBrown --- fs/dcache.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index ae726f3ff0cb..50fbbcceca01 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -3052,6 +3052,9 @@ static void copy_name(struct dentry *dentry, struct d= entry *target) * entries should not be moved in this way. Caller must hold rename_lock, = the * i_rwsem of the source and target directories (exclusively), and the sb-> * s_vfs_rename_mutex if they differ. See lock_rename(). + * + * If @dentry and @target have the same parent, then neither is + * moved in the d_sib list. */ static void __d_move(struct dentry *dentry, struct dentry *target, bool exchange) @@ -3119,15 +3122,20 @@ static void __d_move(struct dentry *dentry, struct = dentry *target, } else { target->d_parent =3D old_parent; swap_names(dentry, target); - if (!hlist_unhashed(&target->d_sib)) - __hlist_del(&target->d_sib); - hlist_add_head(&target->d_sib, &target->d_parent->d_children); + if (target->d_parent !=3D dentry->d_parent) { + if (!hlist_unhashed(&target->d_sib)) + __hlist_del(&target->d_sib); + hlist_add_head(&target->d_sib, + &target->d_parent->d_children); + } __d_rehash(target); fsnotify_update_flags(target); } - if (!hlist_unhashed(&dentry->d_sib)) - __hlist_del(&dentry->d_sib); - hlist_add_head(&dentry->d_sib, &dentry->d_parent->d_children); + if (dentry->d_parent !=3D old_parent) { + if (!hlist_unhashed(&dentry->d_sib)) + __hlist_del(&dentry->d_sib); + hlist_add_head(&dentry->d_sib, &dentry->d_parent->d_children); + } =20 /* * Adjust parent refcounts if either d_children ended up empty. --=20 2.50.0.107.gf914562f5916.dirty From nobody Fri Oct 2 10:08:34 2026 Received: from flow-b6-smtp.messagingengine.com (flow-b6-smtp.messagingengine.com [202.12.124.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8B2822571A0; Mon, 3 Aug 2026 01:39:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721147; cv=none; b=rWi9uoja/W953YMWC+aCXwpQltLViLYVQtmauzZYKZFXiBkrne3mr0tZvdm/hDsDnbQ/MTtXznPQViYbW2k1WMTzfNwWNT8KHvJrh/fpFdrJfAeCWtk5/BHUFFvRyKoAhLPK8fJdirnvbe8fooToR6k7NlJg8M6P2AKH9T6dq4E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721147; c=relaxed/simple; bh=80x5dRqEVgRZsTTLHRvw75oA1m3g+7bZHj0ZG8oOnKA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fqYS1HvkRDtPWg6iruxnzizyVoy1q/+cS88dNlA1FrYUSQycaOhC5qmcT6KBQUE7RbEht5dYiGuCrdzR5SBZ/P5h5boyO4PXddnEBqRdondI0iBl5sQjSmYmr0ULUR8vRHINTDHpRPeIaYnjC9PV1aInomGmSMfBchQbwkurVS8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net; spf=pass smtp.mailfrom=ownmail.net; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b=A6Rmhhhf; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=Eh76sA7a; arc=none smtp.client-ip=202.12.124.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ownmail.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b="A6Rmhhhf"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="Eh76sA7a" Received: from phl-compute-09.internal (phl-compute-09.internal [10.202.2.49]) by mailflow.stl.internal (Postfix) with ESMTP id 40A731300120; Sun, 2 Aug 2026 21:39:04 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-09.internal (MEProxy); Sun, 02 Aug 2026 21:39:04 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ownmail.net; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to; s=fm3; t=1785721144; x=1785728344; bh=S3v8RX+VmBHxPtS8fSNJM421/tOiLSUqqUod+SOCtME=; b= A6Rmhhhf0nO1XtDsEoDaMtKjAPwdXKOI1sEE9w5rnodRZEclpfCO5IE8XnTg35H2 rTj0Qfr1zNC2zHS36usP+Dx/09CwAkYseKjSAPxQPOLWzqqLc8P3Ejz1xgLD/qRR rlUFzINLzBRSW7g9/VSqBNOxcN8TDn2aTtdngBRnExovkGFJrD/ENcAky4eLC9bT vh9P0+lF8YIGloSysx513T/rbLrB91oY1NsclNKwvSzUHS4BhWCNoNE9Qfd0jWJj oW08QozXbipYVX0t0D6H+lnQ68kjinSQsVPCT3beL5/iP1el1sy5CFAvCuptLZ5C UZ3F9eRQzah03h46i5vQ9A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1785721144; x=1785728344; bh=S 3v8RX+VmBHxPtS8fSNJM421/tOiLSUqqUod+SOCtME=; b=Eh76sA7axP5FH1G6I MTzLs4OF0dDWwZejFEwU4Er5K5gTyCjewiJUMLyrKNB8WZwmJyCc3nEqCNKPmw3S QreJx9No+JUEcfxqXPdZdqbnL71fpwSPCF3moc9KpY443NraOHbhLfYG2PH6/fk6 1TtBEvnEQnxOtiGPfNWmeFYIbCaZdg9ci0bs7ZfKpujDZYLx/hb1b+3Ttd8411gz lT2JNNFOqNehlmvLE3j/THHgo3MY3Ak2EFKaUmNPlLOjhp4GZIrEtFPh9JJsKPbT XH/eBhZIg1etNggSP553UdAt9t/6LtT8JpP5DL759iNG0vnn2Y4D59edWHlwV3h7 Xvq3g== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFA/0zm7OzeplXRNvaNNmULnG0bsSwLfs+E1fp/q4OBdNvpsKhweFt4elT9lXHd+G hTM4MVvIxFfT4f1Y7HBQ1gMr4yL539AvDYksd/SsisrtMNq+EqTkOTQTuzQd8lMMFdAmse D1YJ0L60HAoZcUzOgHo9DuzP/4Ow8ItiPyTEjn1bK4Jn1nUlo/POLPXyt3mK9JNNNPqU7Y mubipfwUkLYy5ewC3+/+p9hwcyapoHG+ZZ5DTw872VYmOR7ZRvjLOxdnM0/DOmk3uvO26k 9qw+ssl1tYKsL3hrlaerGXMHiVZx0h5rxUc2yzrUGeaNiWDuoRhf7M39GqD2tmd17RvPGA Nr/VxsXZBplXEAzBChxm88250A1v7ImXXn9vSt/kjZ/fLZMvNZFxcO7wit8ESUGvRJbroT dco1dZxYhxEva7KW0Mh7TTDpH7gTLCJQV4jppJl/pYrCEI3+FaPMpeVLdDUxRfCeHNFDrC vt+Xuwj7p2ZtAvCIZ/h3nKpW6Eagc0h45M1fqYM5z3bWcoRliflVWoWDDtQuKbTnftf4N4 AK3R4b+vDLPWp59zNLSVq8UprwFtD1cQwyO7/noMDm+ZaF2YZsTxomZcIu2KT+XpTfFPtR zsxUZa0fgLNil6LtdGWmrCIJaUpCJ1+wJpydsM7+UIWiCnHO3qPtzb6ssi5w X-ME-Proxy: Feedback-ID: i9d664b8f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 2 Aug 2026 21:38:56 -0400 (EDT) From: NeilBrown To: Ian Kent , Chuck Lever , Jake Edge , Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko , Jan Harkes , coda@cs.cmu.edu, Alexander Viro , Christian Brauner , Jan Kara , Trond Myklebust , Anna Schumaker , Amir Goldstein , Andrew Morton , Miklos Szeredi Cc: autofs@vger.kernel.org, linux-kernel@vger.kernel.org, ceph-devel@vger.kernel.org, codalist@coda.cs.cmu.edu, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org Subject: [PATCH v1 11/12] Call cond_reshed() as needed in d_for_each_positive_child(). Date: Mon, 3 Aug 2026 11:21:20 +1000 Message-ID: <20260803012648.2195405-12-neilb@ownmail.net> X-Mailer: git-send-email 2.50.0.107.gf914562f5916.dirty In-Reply-To: <20260803012648.2195405-1-neilb@ownmail.net> References: <20260803012648.2195405-1-neilb@ownmail.net> Reply-To: NeilBrown Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: NeilBrown There are reports that large numbers of negative dentries can lead to soft lockups when walking the d_children/d_sib list, particularly in fsnotify_set_children_dentry_flags(). (See link below) This can be addressed by allowing a schedule during the walk in the same way that scan_positives() (in libfs.c) already does. As we now walk the list in common code, we can add that schedule call to all places that walk the list using d_for_each_positive_child iterators. Doing this involves using an on-stack dentry (about 330 bytes) which is not standard practice but should be safe since Commit 3df5153c5f12 ("make cursors NORCU") made cursors NORCU, confirming that they can safely be released without waiting. Also importantly nothing ever takes a reference on a cursor that it doesn't own. To facilitate this, a new __d_init() is split out of __d_alloc() and used in d_init_cursor() which can be called on an on-stack dentry as is done in the new d_next_sibling_sched(). d_for_each_positive_child*() now use d_next_sibling_sched() if appropriate and they now assert they might_sleep()). Note that d_walk() also walks this list and does not use the new helper. Some instances of d_walk() do abort when a resched is needed, others do not. This patch does not help with those. Link https://lwn.net/Articles/1079407/ Signed-off-by: NeilBrown --- fs/dcache.c | 109 ++++++++++++++++++++++++++++++++++------- include/linux/dcache.h | 23 ++++++--- 2 files changed, 108 insertions(+), 24 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 50fbbcceca01..3678f86fe693 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1885,6 +1885,24 @@ void d_invalidate(struct dentry *dentry) } EXPORT_SYMBOL(d_invalidate); =20 +static void __d_init(struct dentry *dentry, struct super_block *sb) +{ + dentry->d_flags =3D 0; + lockref_init(&dentry->d_lockref); + seqcount_spinlock_init(&dentry->d_seq, &dentry->d_lock); + dentry->d_inode =3D NULL; + dentry->d_parent =3D dentry; + dentry->d_sb =3D sb; + dentry->d_op =3D sb->__s_d_op; + dentry->d_flags =3D sb->s_d_flags; + dentry->d_fsdata =3D NULL; + INIT_HLIST_BL_NODE(&dentry->d_hash); + INIT_LIST_HEAD(&dentry->d_lru); + INIT_HLIST_HEAD(&dentry->d_children); + dentry->waiters =3D NULL; + INIT_HLIST_NODE(&dentry->d_sib); +} + /** * __d_alloc - allocate a dcache entry * @sb: filesystem it will belong to @@ -1894,7 +1912,6 @@ EXPORT_SYMBOL(d_invalidate); * available. On a success the dentry is returned. The name passed in is * copied and the copy passed in may be reused after this call. */ -=20 static struct dentry *__d_alloc(struct super_block *sb, const struct qstr = *name) { struct dentry *dentry; @@ -1922,14 +1939,14 @@ static struct dentry *__d_alloc(struct super_block = *sb, const struct qstr *name) p =3D kmalloc_flex(*p, name, name->len + 1, GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE); if (!p) { - kmem_cache_free(dentry_cache, dentry);=20 + kmem_cache_free(dentry_cache, dentry); return NULL; } atomic_set(&p->count, 1); dname =3D p->name; } else { dname =3D dentry->d_shortname.string; - }=09 + } =20 dentry->__d_name.len =3D name->len; dentry->__d_name.hash =3D name->hash; @@ -1939,20 +1956,7 @@ static struct dentry *__d_alloc(struct super_block *= sb, const struct qstr *name) /* Make sure we always see the terminating NUL character */ smp_store_release(&dentry->__d_name.name, dname); /* ^^^ */ =20 - dentry->d_flags =3D 0; - lockref_init(&dentry->d_lockref); - seqcount_spinlock_init(&dentry->d_seq, &dentry->d_lock); - dentry->d_inode =3D NULL; - dentry->d_parent =3D dentry; - dentry->d_sb =3D sb; - dentry->d_op =3D sb->__s_d_op; - dentry->d_flags =3D sb->s_d_flags; - dentry->d_fsdata =3D NULL; - INIT_HLIST_BL_NODE(&dentry->d_hash); - INIT_LIST_HEAD(&dentry->d_lru); - INIT_HLIST_HEAD(&dentry->d_children); - dentry->waiters =3D NULL; - INIT_HLIST_NODE(&dentry->d_sib); + __d_init(dentry, sb); =20 if (dentry->d_op && dentry->d_op->d_init) { err =3D dentry->d_op->d_init(dentry); @@ -1969,6 +1973,77 @@ static struct dentry *__d_alloc(struct super_block *= sb, const struct qstr *name) return dentry; } =20 +/** + * d_init_cursor - initialise an on-stack dentry cursor + * @dentry: the dentry to be initialised + * @parent: dentry of parent where cursor will be used. + * + * A DCACHE_DENTRY_CURSOR is initalised for use in marking + * a place in the d_children/d_sib list. While sb-related + * fields are filled in, they should never be used. + * The filesystems d_init is not called and a final d_put() + * should not be called, else d_release would be called. + */ +static void d_init_cursor(struct dentry *dentry, struct dentry *parent) +{ + const struct qstr *name =3D &slash_name; + char *dname; + + /* + * We guarantee that the inline name is always NUL-terminated. + * This way the memcpy() done by the name switching in rename + * will still always have a NUL at the end, even if we might + * be overwriting an internal NUL character + */ + dentry->d_shortname.string[DNAME_INLINE_LEN-1] =3D 0; + name =3D &slash_name; + dname =3D dentry->d_shortname.string; + + dentry->__d_name.len =3D name->len; + dentry->__d_name.hash =3D name->hash; + memcpy(dname, name->name, name->len); + dname[name->len] =3D 0; + + /* Make sure we always see the terminating NUL character */ + smp_store_release(&dentry->__d_name.name, dname); /* ^^^ */ + + __d_init(dentry, parent->d_sb); + dentry->d_parent =3D parent; + dentry->d_flags |=3D DCACHE_DENTRY_CURSOR | DCACHE_NORCU; +} + +/** + * d_next_sibling_sched - return next sibling, but schedule() first + * @child: current child + * + * This behaves like d_next_sibling(), but drops the parent d_lock + * and calls cond_resched() to avoid any soft-lockup. A cursor + * is inserted as place holder. + * + * Caller must hold the parents d_lock, and must hold a counted + * reference on the parent. + * + * Returns: the next sibling, or NULL if there is none. + */ +struct dentry *d_next_sibling_sched(struct dentry *child) +__must_hold(&child->d_parent->d_lock) +{ + struct dentry cursor; + + d_init_cursor(&cursor, child->d_parent); + hlist_add_behind(&cursor.d_sib, &child->d_sib); + spin_unlock(&cursor.d_parent->d_lock); + cond_resched(); + spin_lock(&cursor.d_parent->d_lock); + child =3D d_next_sibling(&cursor); + __hlist_del(&cursor.d_sib); + if (hlist_empty(&cursor.d_parent->d_children)) + dput_dlock(cursor.d_parent); + WARN_ON(d_count(&cursor) !=3D 1); + return child; +} +EXPORT_SYMBOL(d_next_sibling_sched); + /** * d_alloc - allocate a dcache entry * @parent: parent of entry to allocate diff --git a/include/linux/dcache.h b/include/linux/dcache.h index cabf05e74b1f..f7d5954c58da 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -656,10 +656,15 @@ static inline struct dentry *d_next_sibling(const str= uct dentry *dentry) return hlist_entry_safe(dentry->d_sib.next, struct dentry, d_sib); } =20 +struct dentry *d_next_sibling_sched(struct dentry *child); + static inline struct dentry *d_next_positive(struct dentry *child) { do { - child =3D d_next_sibling(child); + if (need_resched()) + child =3D d_next_sibling_sched(child); + else + child =3D d_next_sibling(child); } while (child && !d_really_is_positive(child)); return child; } @@ -691,9 +696,11 @@ static inline struct dentry *d_first_positive(const st= ruct dentry *parent, * which have at some point in the past been positive. */ #define d_for_each_positive_child(child, parent) \ - scoped_guard(spinlock, &parent->d_lock) \ - for (child =3D d_first_positive(parent, NULL); child; \ - child =3D d_next_positive(child)) + if (({might_sleep();0;})) ; else \ + scoped_guard(spinlock, &parent->d_lock) \ + for (child =3D d_first_positive(parent, NULL); \ + child; \ + child =3D d_next_positive(child)) =20 /** * d_for_each_positive_child_continue - iterate over remaining positive ch= ildren @@ -710,9 +717,11 @@ static inline struct dentry *d_first_positive(const st= ruct dentry *parent, * */ #define d_for_each_positive_child_continue(child, parent) \ - scoped_guard(spinlock, &parent->d_lock) \ - for (child =3D d_first_positive(parent, child); child; \ - child =3D d_next_positive(child)) + if (({might_sleep();0;})) ; else \ + scoped_guard(spinlock, &parent->d_lock) \ + for (child =3D d_first_positive(parent, child); \ + child; \ + child =3D d_next_positive(child)) =20 void set_default_d_op(struct super_block *, const struct dentry_operations= *); struct dentry *d_make_persistent(struct dentry *, struct inode *); --=20 2.50.0.107.gf914562f5916.dirty From nobody Fri Oct 2 10:08:34 2026 Received: from flow-b6-smtp.messagingengine.com (flow-b6-smtp.messagingengine.com [202.12.124.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8646F2E6CAB; Mon, 3 Aug 2026 01:39:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721157; cv=none; b=TffIN9hop90xkJ2NwkdJTYuiH1T2tBBGOZi0J3gjfCyYjGlrG2UODiaU9lD2Bj+qSCNeUN9p6QCUO4eNgerzjch4ut+GSNNNG+klbdVx9hKSsGUHyp3J/IBrB2MomUC1OzyTj3tvrR7d0YllqzyZBgjBpj/TOn4umLMZQf/sLrY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785721157; c=relaxed/simple; bh=xah1IZBUivqmQDuiMbVbkX4ugtrL2Xtzx9N4QCKerkc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p1+gWGu2VN8d1zz1uIL58yyzz1F1mCIS9uVDy2CiIp1Q1Nm7W7ZXbzwJY+6h3b/8Qn3k/vH/G9VOcVC/f4sQzsSwbGPeWY2LPD091yDilUsoSveWFzKhtnhtfexxBoynsAf90eL/ndunU8UZ9RIyPzVhaFuDWjn97rTMxkm70FQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net; spf=pass smtp.mailfrom=ownmail.net; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b=MmTcyLcM; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=Kcsz9Wpk; arc=none smtp.client-ip=202.12.124.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ownmail.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ownmail.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ownmail.net header.i=@ownmail.net header.b="MmTcyLcM"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="Kcsz9Wpk" Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailflow.stl.internal (Postfix) with ESMTP id 7C7B51300128; Sun, 2 Aug 2026 21:39:15 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-06.internal (MEProxy); Sun, 02 Aug 2026 21:39:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ownmail.net; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to; s=fm3; t=1785721155; x=1785728355; bh=48Fkc2hhO16ufhmd1558xtjY3jyS/m26wkZxQxAYLN4=; b= MmTcyLcMzoglUJq5DvMYnZYd5dxPosypo6M/Czfn6KbZhjhaV5cGXYOeTv4oR0TT sgQeNmTSOWtAIK1eFjh0CppB+cW3OJOGTEKFbINbZG+7FMGsDxBdw7q2B9GXviVm trc4zXspmN/Ddr2UGslL7EdXUOGsx0inSYQAn4Tnm8JA5WXxbhw2lujtXlZ2j5uS Oi9DUHD2G5p/kuC+nIFF9/K/rDiy2GpJykkv6lPqSgOCTwIpZKFEz2Yang/bbglA //wkYWxj5HmN/ShJAlYORy8aCkVzy4YMuaUlsR7cM2m80DBbodnC+Qyl3uUgFxwg JFOaflya03Xaiy9RAjuWoQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1785721155; x=1785728355; bh=4 8Fkc2hhO16ufhmd1558xtjY3jyS/m26wkZxQxAYLN4=; b=Kcsz9WpkZmbKKAn7R BSWde2q3tmv1TuCv/DZM6/QYpvZdyb4+1GtF0ImDSLUDaSYmHIEXV7e3AiN1/idL 4hyTU7pBZjIKFjfwp7w/NuJuT+GJgpmz/RnV8PIZrcPawUhFJ6/bCFw6T3KuHeKe FfXEpr4K+fRWcUFeMt/hgZm38kep6eBowrLSAijJJdo9NIS0vpYXcz76uzCigAYS LE3zGsGX7ATZz+Ce1bTJtoum4SRvYsAW7S5oqdV2vXJKwHPVprraItJvn2SidkDF Et0n8U4syijG6V2teDdrN9r9IYsdi6JiZ3lEAIkpaVyxkkrr1HgGA0G8kccUYo7g MhIfg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEkjpQitAtmxGBQYKqyuxI2Zkeo3c6RoaKCNErqeb7OpTUkwok+umPK8wjjzKilLR oEkJ4cvJVGjSJ84RQAU1yMp4OnVAa0j48I+IZh9Fdm8T9NlXb22vW2b++I/w1xpR0D9cGg PY5vxXMwbazIrQndnHZZeUaDjtiO7oMO4JfvURQOW8xpTRIAhWmk/yj3tGiTCFDkK11PUi 8zP+PAM6p9S6yYk+YxJK09JqJLxfofUFwglAMcxid0fjJ/8eCuMBF6ZgJ9khwYNTvmmvDv XHb98vv+s9pbhqVhgG7tjgoBPJWqvJT0PbLNRH63wXqa3Yd9frMtJBXjxnj2koyaKciEdl uFMMz/4CEUcGyouzkIImU/OhVANGkyFS72dBLv8gabALYxnV5Tqh6acfylQZWUdliw+z9E bY051siIlw2Ox7ryWHJ5c0bt3NjEccKlc099E7t+VNREBTdm8Jj+6iKP0C+r6YGgyGTDcw q4sQLDcx7PBXLdmd26XcAXfyMzQu66MviRh0kq6A4mXxLyX9JOUvnTnZ3BoCPIz3FNVnj/ brhwej9bFhJXHOMEsW1uxSwNwWTzwQeozhxzEJicXviJfH0NqSaAH6OGUX5cgpxPJgji6/ N74k5PdE+TwvVvSOKrfR2olAgDTA2/Y+MSeg4U8X3elFfFCDTVNchi2yLV9g X-ME-Proxy: Feedback-ID: i9d664b8f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 2 Aug 2026 21:39:07 -0400 (EDT) From: NeilBrown To: Ian Kent , Chuck Lever , Jake Edge , Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko , Jan Harkes , coda@cs.cmu.edu, Alexander Viro , Christian Brauner , Jan Kara , Trond Myklebust , Anna Schumaker , Amir Goldstein , Andrew Morton , Miklos Szeredi Cc: autofs@vger.kernel.org, linux-kernel@vger.kernel.org, ceph-devel@vger.kernel.org, codalist@coda.cs.cmu.edu, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org Subject: [PATCH v1 12/12] libfs: remove cond_resched() from scan_positives() Date: Mon, 3 Aug 2026 11:21:21 +1000 Message-ID: <20260803012648.2195405-13-neilb@ownmail.net> X-Mailer: git-send-email 2.50.0.107.gf914562f5916.dirty In-Reply-To: <20260803012648.2195405-1-neilb@ownmail.net> References: <20260803012648.2195405-1-neilb@ownmail.net> Reply-To: NeilBrown Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: NeilBrown Now that d_for_each_positive_child_continue() calls cond_resced() as needed, scan_positives() doesn't need to any more. Signed-off-by: NeilBrown --- fs/libfs.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/fs/libfs.c b/fs/libfs.c index c0771e8b645c..b4c9cfdc1907 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -105,7 +105,6 @@ EXPORT_SYMBOL(dcache_dir_close); * If no such element exists, NULL is returned. */ static struct dentry *scan_positives(struct dentry *dentry, - struct dentry *cursor, struct dentry *last, loff_t count) { @@ -122,15 +121,6 @@ static struct dentry *scan_positives(struct dentry *de= ntry, break; count =3D 1; } - if (cursor && need_resched()) { - if (!hlist_unhashed(&cursor->d_sib)) - __hlist_del(&cursor->d_sib); - hlist_add_behind(&cursor->d_sib, &d->d_sib); - d =3D cursor; - spin_unlock(&dentry->d_lock); - cond_resched(); - spin_lock(&dentry->d_lock); - } } dput(last); return found; @@ -157,7 +147,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offse= t, int whence) inode_lock_shared(dentry->d_inode); =20 if (offset > 2) - to =3D scan_positives(dentry, cursor, NULL, offset - 2); + to =3D scan_positives(dentry, NULL, offset - 2); spin_lock(&dentry->d_lock); hlist_del_init(&cursor->d_sib); if (to) @@ -191,7 +181,7 @@ int dcache_readdir(struct file *file, struct dir_contex= t *ctx) if (ctx->pos > 2) next =3D dget(cursor); =20 - while ((next =3D scan_positives(dentry, cursor, next, 1)) !=3D NULL) { + while ((next =3D scan_positives(dentry, next, 1)) !=3D NULL) { if (!dir_emit(ctx, next->d_name.name, next->d_name.len, d_inode(next)->i_ino, fs_umode_to_dtype(d_inode(next)->i_mode))) @@ -445,7 +435,7 @@ offset_dir_lookup(struct dentry *parent, loff_t offset) MA_STATE(mas, &octx->mt, offset, offset); =20 if (offset =3D=3D DIR_OFFSET_FIRST) - found =3D scan_positives(parent, NULL, NULL, 1); + found =3D scan_positives(parent, NULL, 1); else { rcu_read_lock(); spin_lock(&parent->d_lock); @@ -467,7 +457,7 @@ offset_dir_lookup(struct dentry *parent, loff_t offset) spin_unlock(&parent->d_lock); rcu_read_unlock(); if (found && !simple_positive(found)) - found =3D scan_positives(parent, NULL, found, 1); + found =3D scan_positives(parent, found, 1); } return found; } @@ -493,7 +483,7 @@ static void offset_iterate_dir(struct file *file, struc= t dir_context *ctx) if (!offset_dir_emit(ctx, dentry)) break; =20 - dentry =3D scan_positives(dir, NULL, dentry, 1); + dentry =3D scan_positives(dir, dentry, 1); =20 if (!dentry) goto out_eod; --=20 2.50.0.107.gf914562f5916.dirty