From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr1-f54.google.com (mail-wr1-f54.google.com [209.85.221.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED7142F851 for ; Wed, 29 Jul 2026 00:59:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.54 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785286785; cv=none; b=CWl5ZxFqGrI788+YSL8m7R2rwgcE2uJ1sPjavgjjHNQekADqW8hOfB2pHAEdFj8ivk4B01ggj7WrA64oZvCmMCosuY11gpWtZDs8J3dQP2ui3ZwDbkHyOKKafUZzAr5arui02ocich97JCTmMPT2UMFhcxJ4YolCLD8YtHhnlSE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785286785; c=relaxed/simple; bh=0KWF7l74NSCZbAciJn0VhYbORBxGH+vyhWCqMZH8cRs=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=fk2N4UoJQh6o1iVuyRrmV6LrazACXoCGAieZfFMbvruhGYd0vJG83Tx1kX/DQ/c4HvAuexUPcmTtCbGy7V4V44q73chA1hcyya6t0HyApAzpYE5T9VAUqq4xLJ8BkdOwyGFcDVqMhZhVsdUthXOudZWHVYI1tmXQ51/vpUcjG1s= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Tv6iX0Ys; arc=none smtp.client-ip=209.85.221.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Tv6iX0Ys" Received: by mail-wr1-f54.google.com with SMTP id ffacd0b85a97d-47c6e9a694bso289460f8f.1 for ; Tue, 28 Jul 2026 17:59:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785286781; x=1785891581; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=d6+QL24j4d2zpvhuMtnoDkWU1oAuvMuECjOV2EZkZcU=; b=Tv6iX0YsEE1+h94f4YZ933PmwHuxS+TYiuXMF6q/yfQ5AB/xMF/hGoNoO5q299rT5N cwWH4Y7dV4g0xtsgYM8TqtmvkufaWTLE9F21FqbtQMUp0gLvqnXP7rhkQwRmzS1X2qQr O2HVdy2+gFbRXNI5Uy1/L0/XHxNqMmPflvg6VAuJJ5SDsEmtufa6TrYmZNmEX7s2C1Dq vank32z9q2ehxUjrAYSPDWwjGfCGwpHXqXxQjKyKZL7edLu0c0BBZ+d503jSxfhOi1Ew rY6p3y6pjjKcsZg0ICLqyt6adVQ3QnCfVORQyEl6YzvIZuqi2wMY2cnOkQl5AYO6eNKB DUrg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785286781; x=1785891581; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=d6+QL24j4d2zpvhuMtnoDkWU1oAuvMuECjOV2EZkZcU=; b=dNr8Y4SJhm4CyCDuo0LfbKi2+kvCLTnU3561oRbw0xmh8drUfPQXaCjt1/Hq6NfZew oAxp+OmZqFRQBNKSHjjsBSxHb6ZC+spifjKpT7uYz/FtejCcpMU3TH+xwmIMqwEYPeOs fIDHO1QnAn87B68zCQp+TlYfksZCjQMM8RcR/ZkZeDHVNx9/VME/uWjiA7l3oA/ZLNFD ACYTDmv+QFrSsaT6XR4bOjV5NE1NY9kHZ2vumMQslCJmD1RiTM5LQN6CiAOy7V66dY/1 mO6flJj8am0A6x2yw6zF8i7qBZej8YzqrILxY+eKJ5vXIV/qZ2MCSJiZfmnKwRnrkqFq cELA== X-Forwarded-Encrypted: i=1; AHgh+RqD8yRpyHj0t6zDCCNTECdi81bu/CNxtg4xv8QAu1926IgIwM8YeN5FewG89gB/vIafhecmCm1nClc/K6I=@vger.kernel.org X-Gm-Message-State: AOJu0YzR3JyiI7bjrJBuWb+hIRzUWRTAoaPE5WtZr8nTvVJO/UrfySne y92Xkmmax5Oj+Q3W4OuLwqNQ659tzKvTbejCeMD4EFwWJHgnJwc3DCsF X-Gm-Gg: AR+sD1275bKN0YmMRlSMAtt5xDPknQmHrLxl9N468Ntd85Nn9Ok90T4oG5f1zuMh1lZ b6lq0FZNWCDMbqdzXs2lH/ol7xyI+RJt1ITGaZlAIwkYvUx4x+7NCHrf7lWhFk89TZwP9vsm7r7 0+/HfhQb2B4dKh00mCLBQOcHJgfhxDGnlL74Y1ym1NnSF+nC6irFzuv2XN4UpSAEV7hRbZcdyHU rzh0tKl3wuKGjnPWM2rkI0tX7VHkn9rrEG2DbwcFNxLjMEB+7OOjJ8/gS/ffsNKW4Pum46eRVMB mPLIZFQeM6AJT2HcPwbTN4sjCexxoluwRM1hcpSUCz0mh4SmQZGoTXLanPnMUfjtcEbw2yC+tgb tNt3rV6I5CW6jSbXomERuaHiJaHp+2BV4/029k03jSQ8EHo0IqSNLAdb+dCM+hn78BisTx7H2At uMfgNiom/W2rxZDLjaKSvu+IE5i3B19Z9yreZBwIj9Eaqf0sXLszgjRUbITaoC2CAIeOQ+MHDIt Z6yu0qSa1+jdTlcyzep2McofnQArlV+CVWotlUmyGYFGFp5rjhL2RTnATAuSWhhXJTG/RXl9ANm Py2+MI+MnFg7yWC0O9ycA3toiBY2rWKwG2yoT8NRjmPyHncY4IKaKMlui+3TICopAcGBuHxb2s+ 5fY8mfA== X-Received: by 2002:a05:6000:1861:b0:47f:80d1:be0a with SMTP id ffacd0b85a97d-47fb1e924ccmr5560631f8f.14.1785286780935; Tue, 28 Jul 2026 17:59:40 -0700 (PDT) Received: from MacBook-Pro-von-Karl.localdomain (dynamic-2a02-3100-b323-2b01-0d98-9fe8-a4cd-78ab.310.pool.telefonica.de. [2a02:3100:b323:2b01:d98:9fe8:a4cd:78ab]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47fb6abc703sm3598526f8f.9.2026.07.28.17.59.39 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Tue, 28 Jul 2026 17:59:40 -0700 (PDT) From: Karl Mehltretter To: Alexander Viro Cc: Karl Mehltretter , Christian Brauner , Jan Kara , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH] dcache: keep shrink_dcache_for_umount() making progress on busy roots Date: Wed, 29 Jul 2026 02:59:33 +0200 Message-Id: <20260729005933.15858-1-kmehltretter@gmail.com> X-Mailer: git-send-email 2.39.5 (Apple Git-154) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Commit e9895609cb7f ("wind ->s_roots via ->d_sib instead of ->d_hash") moved secondary roots from ->d_hash to ->d_sib. Secondary roots are now d_unhashed(), so __d_drop() returns without removing them from ->s_roots. Consequently, d_drop() in do_one_tree() no longer guarantees progress through the list. If a secondary root has an unexpected extra reference, do_one_tree() reports it, but its final dput() cannot evict it. The root remains ->s_roots.first and the loop selects it forever, holding ->s_umount for write and repeatedly reporting the same dentry. Before e9895609cb7f, ___d_drop() special-cased IS_ROOT dentries and removed them from ->s_roots regardless of their refcount. Commit 9c8c10e262e0 ("more graceful recovery in umount_collect()") deliberately made busy dentries nonfatal: report them and finish the unmount rather than BUG() while holding ->s_umount. Detaching busy secondary roots from ->s_roots restores the previous behavior. A permanently leaked reference remains leaked after unmount; if the extra reference is only delayed, its final dput() may run after teardown has advanced and hit poisoned or freed filesystem state. The current code avoids that late cleanup only by looping indefinitely under ->s_umount for a real leak. Restore that behavior by removing each live secondary root from ->s_roots after taking the temporary reference. In the normal case, dentry_unlist() finds ->d_sib already unhashed when eviction occurs. Fixes: e9895609cb7f ("wind ->s_roots via ->d_sib instead of ->d_hash") Assisted-by: Claude:claude-fable-5 Signed-off-by: Karl Mehltretter --- Notes: The reproducer mounts ramfs, allocates a fresh directory inode on its superblock, calls d_obtain_root(), and deliberately retains the returned dentry reference before unmounting. The fresh inode ensures that no existing alias is returned. d_unhashed() reports umount returns v7.1 0 1 yes 7.2-rc4+ unpatched 1 13013 no 7.2-rc4+ patched 1 1 yes All 13013 reports in the unpatched run identified the same dentry, confirming that the loop kept selecting ->s_roots.first. With the patch, diagnostics match v7.1: one busy-dentry warning, one busy-inode warning, and no list-debug corruption. This injects a pre-existing refcount bug; no in-tree filesystem was found to create one by itself. Detaching the root guarantees progress for a permanent leak. If the extra reference is merely delayed, however, its eventual dput() can run after teardown has advanced. Leaving the root attached avoids that late cleanup but retries indefinitely for a permanent leak. fs/dcache.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/dcache.c b/fs/dcache.c index 3e9af9de7074..2aff15ee07fb 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1832,6 +1832,9 @@ void shrink_dcache_for_umount(struct super_block *sb) wait_for_completion(&wait.completion); } else { dget_dlock(dentry); + // A busy root survives do_one_tree(); unlink it so the + // ->s_roots loop keeps making progress. + unlink_secondary_root(dentry); spin_unlock(&dentry->d_lock); do_one_tree(dentry); } -- 2.53.0