From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 9E59F4195CD for ; Thu, 9 Jul 2026 17:40:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783618846; cv=none; b=cXAVCDtL6dv13jk2+nQ+cQ0gI7MXPzN2CxmpaNWGMOJ/BcoUf8nKQnHxbIc3ZilZWPPYppdKLGyB/4eX6kaWmaFFXITV2xZ/PVS8W+GYVHvRvOT6t/TkvHhOXrCmpQZvHa6lMBOwMj2p4y4jhoB76tUWolws/31l93YtmTiFaYE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783618846; c=relaxed/simple; bh=EqwgcZQiZBN6/nbg3hs/pubZmkCQFawO2A+sGp/A4Ts=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=YLUadFiLOBg1vXuClGDdpp6PIHZ61a4+OyaAZU+JO3cGF84Abv7ArjiRmMQQpsOMZki7wza9gGyRVv4WwIqaf12d8y2UDY6K1gm58oqJNj7nu0wnuYqd2G/19K6IH8Udf8YDuFjlOwbmAoQeTjdiHJPShtp31Lv7EuIWRztVZeY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lLraV6jK; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lLraV6jK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F18DA1F00A3F; Thu, 9 Jul 2026 17:40:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1783618845; bh=v7+E69bv0aGtGoOt+hE5CG8yYfQpqL5RcTPvarlbjho=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=lLraV6jKWY+ZjbQpbzxhbGOEQXkd+2CKiOzvs0wv8zAeIbJAdAlAouH+9hyhAF1Z7 RDfcd6uKPMelI/VmsDKiZdf7Fg7y5Fha6UCA3W14LlbFci7RiQKPGCc+nRjXgdohPp 3f05NRNdRhYkLDmZorQYut9VlNq4wrurXeRBfKxjIZ5lLHj8pwnnz+w3qTI5f3vUpO oq9cBpI4jK/jMnFIcn9sjTxM7WA1p7oFDU0H4FiyGXOKipqX7pgEM0sybCGpnGFr79 OkFGjhfFcIOgFYT+TpTYfM1k/1J8VgB2LqxPFBfC8+3fM0QBzlzgfSJFtvFma5/PHG Ul6IFmzOKy2Hw== From: Chuck Lever Date: Thu, 09 Jul 2026 13:40:32 -0400 Subject: [PATCH v4 9/9] NFSD: Release the export reference when reaping open stateids Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260709-cel-v4-9-1d519d9be0cb@kernel.org> References: <20260709-cel-v4-0-1d519d9be0cb@kernel.org> In-Reply-To: <20260709-cel-v4-0-1d519d9be0cb@kernel.org> To: Jeff Layton , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: linux-nfs@vger.kernel.org, sashiko-bot , Chuck Lever X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=3151; i=cel@kernel.org; h=from:subject:message-id; bh=EqwgcZQiZBN6/nbg3hs/pubZmkCQFawO2A+sGp/A4Ts=; b=owEBbQKS/ZANAwAKATNqszNvZn+XAcsmYgBqT90WT9Cu6ywnQZz7vhTKykZJgWCAznkBkdqxR 6JxHDL1M02JAjMEAAEKAB0WIQQosuWwEobfJDzyPv4zarMzb2Z/lwUCak/dFgAKCRAzarMzb2Z/ lx5fD/0eANuM2ERFfUAdp7JRjH0WZFfsziYJgcnKAodWXShgk51c5kSI9evFXZWBJmvO/Z5Llk5 5jZI0c+Q270fbujnVvTlo6oUvxjWkECJphwoIVVJydSDvdTP+YZfmRf/cFmV4m/8dOtyYEFCVr9 hqKKn1msZk9B4k3iEZ2gky66TALYJQwzG93FyUYmPTO7dcwjumUiR+TCW8RlXmWOYSry3trWVcU CmiiKN/Zl1UXh161gm9KDADXGnk3uYRKytrmMYYWkQmbFu65Ht6eACiWfkVJ3k8Z6r+QLgf5tyf dNo6uCM7JBuiNUbBtazLJuubRwEXvD8HtgiTHC1zFymQDXM2zxCImPg0tixlrRXOgqbmsequLOJ Kh2lwg2JIPizXcAlLJIVMTvzUIhRPqv6GlJDXRfP1B6elQfhPAx/ffOdCwGbeYIYmkn1HN48f8m phaZTs0HSp3kzPaqQG2033Fpje2wk4lQ9Sd+8es2pjLBgS6sj0ktgjPiajwSqmjN3Km+QB2RsjL BNYw+rCFHTOGYp3UXgIvGFAzIOplma7oJVxR+7oaq9Xs6Y10DuDUhtuDQ52DH25Q+z7yM7oFEw7 kXV/UTPx6UI6URciJ/tl43Zs9eB9oGmy9Xg52tM5ptBsTP35FYY8FTzld1O2HzhFR1R8RGQ7Pf4 K/IQaSW20CP3mcQ== X-Developer-Key: i=cel@kernel.org; a=openpgp; fpr=28B2E5B01286DF243CF23EFE336AB3336F667F97 nfs4_put_stid() releases the svc_export tracked in nfs4_stid.sc_export, but free_ol_stateid_reaplist() frees open and lock stateids by calling ->sc_free() directly, bypassing that path. An open stateid takes an sc_export reference in nfs4_open() and a lock stateid takes its own in init_lock_stateid(); both reach free_ol_stateid_reaplist() through their normal teardown, the open stateid via release_open_stateid() and the lock stateid via nfsd4_release_lockowner(), each through put_ol_stateid_locked(). The reference is therefore never dropped, pinning the export and blocking unmount for the lifetime of the stateid. Release sc_export in free_ol_stateid_reaplist() the way nfs4_put_stid() does. ->sc_free() runs once per stateid, and a stateid reaches free_ol_stateid_reaplist() or nfs4_put_stid() but never both, so the reference is dropped exactly once. Revoked stateids reach this path with sc_export already cleared by drop_stid_export(), so they are skipped rather than double-freed. nfs4_put_stid() itself read sc_export before acquiring cl_lock. drop_stid_export() clears that field and releases the reference under cl_lock, so a concurrent revocation could drop the export in the window between the read and the final put, releasing the same reference twice. Read sc_export while cl_lock is held so the two paths serialize and the reference is released exactly once. Fixes: ba0cde5dc81d ("NFSD: Track svc_export in nfs4_stid") Reported-by: sashiko-bot Closes: https://sashiko.dev/#/patchset/20260707-cel-v3-0-7c0cc16fd54f@kernel.org?part=9 Signed-off-by: Chuck Lever --- fs/nfsd/nfs4state.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 20556b8f186a..e988dfebf75e 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1272,9 +1272,9 @@ alloc_init_dir_deleg(struct nfs4_client *clp, struct nfs4_file *fp) void nfs4_put_stid(struct nfs4_stid *s) { - struct svc_export *exp = s->sc_export; struct nfs4_file *fp = s->sc_file; struct nfs4_client *clp = s->sc_client; + struct svc_export *exp; might_lock(&clp->cl_lock); @@ -1285,6 +1285,8 @@ nfs4_put_stid(struct nfs4_stid *s) idr_remove(&clp->cl_stateids, s->sc_stateid.si_opaque.so_id); if (s->sc_status & SC_STATUS_ADMIN_REVOKED) atomic_dec(&s->sc_client->cl_admin_revoked); + /* Read under cl_lock to serialize with drop_stid_export(). */ + exp = s->sc_export; nfs4_free_cpntf_statelist(clp->net, s); spin_unlock(&clp->cl_lock); s->sc_free(s); @@ -1744,6 +1746,7 @@ static void free_ol_stateid_reaplist(struct list_head *reaplist) { struct nfs4_ol_stateid *stp; + struct svc_export *exp; struct nfs4_file *fp; might_sleep(); @@ -1753,9 +1756,12 @@ free_ol_stateid_reaplist(struct list_head *reaplist) st_locks); list_del(&stp->st_locks); fp = stp->st_stid.sc_file; + exp = stp->st_stid.sc_export; stp->st_stid.sc_free(&stp->st_stid); if (fp) put_nfs4_file(fp); + if (exp) + exp_put(exp); } } -- 2.54.0