From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794585379; b=yRti+7WDv485I0JKX6vO9D0sHyTma2fFoR11oSTDSY+MOVyadgSfobjINVuro5mBs6/1 xKRz9H68f232wbqn7TKAS7e9dVsiqjmn6CkpepzOkSa7x7j9Q69trxVGaTghq9zIP+7zk U8TL6uIKnGtM9vZJQnDughl5Gfek9nLfySs/sQ4nuAHqAPv5KHZ7L9Cj2rkoOSCeYF8Mu ti91fpaRU4zcRbDhGDHmJSKFjjmRHXhj50x+A52vCdTrQK/o6AoOrYdblu7tWIQoeWSaf bIRIk2mQQupzCq9l15lzTkKGaaPrYPCtM+FwJ6EYLnPi4nA2fa+NFmOa1SjxJoVhUEw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794585379; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:User-Agent:X-stable:X-Patchwork-Hint: MIME-Version:Content-Transfer-Encoding; bh=kp94G0rnmJjXe8eFFDBEjxapyTd/uX1gOMbFM2O0K2k=; b=14CoKzL2YsI3D3f9MKtEDib3Ukoea7o+g/firAajeNAHZWGh7xHUuPZnIC7ZxdOnWrLp kkSztHGCF3wytVfWys/vgqd8+VCqjIt6oEZGhZF8gGSzkF+W55GzA4eReDUN/2wrsIEA/ emcygbA39N2x15Bl18uq/aBPn74rwq9e7du546KiTZFekBhYIGWZ1jaOXWv6Rvwzs39WL +fSBWgyDcfAO5MJO/t3gwNPjBkMIIwE3PnAkudFg5jiKl4up2ctNfIolmERmeU+Z1LBjq AENEXfDg4LXidjHwPiKqnNa8Xk1KFs+48E+8gn/5Aek0SWe81Gbl0pznmz1xeZCfngw== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=FXMIr2cr; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34036606D462; Fri, 13 Nov 2026 15:56:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=FXMIr2cr Received: by smtp.kernel.org (Postfix) with ESMTPSA id D460F1F000CB; Fri, 13 Nov 2026 15:56:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1794585379; bh=kp94G0rnmJjXe8eFFDBEjxapyTd/uX1gOMbFM2O0K2k=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=FXMIr2crKIyrTUqkv5u2oKrGcuS2+ffTwDeKN52sV1Tz7MvJva5T1vDkm/VWgMnAd cvP8hj2+B5z7bkY6bZRlHFiatH2eU2RK54uWnXbMaADBPc/t9PwvvaNEsN7GD6ud6+ 4tBUWO6uQtcM/xzm+UYJkaIkqjtt2AyYYBuviI3w= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Jeff Layton , Chuck Lever , Sasha Levin Subject: [PATCH 7.3 016/507] NFSD: Send a meaningful CB_RECALL_ANY keep count Date: Fri, 13 Nov 2026 10:45:20 -0500 Message-ID: <20261113153753.976483858@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261113153753.358973689@linuxfoundation.org> References: <20261113153753.358973689@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore X-Mailing-List: stable@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 7.3-stable review patch. If anyone has any objections, please let me know. ------------------ From: Chuck Lever [ Upstream commit 9af39c0773ef956039e1ebe9c235532fe6ee1e50 ] deleg_reaper() sets craa_objects_to_keep to zero on every CB_RECALL_ANY. RFC 8881 Section 20.6.3 defines that field as the number of objects the client may keep, leaving the client to choose which of the excess to return, because the server cannot read lack of recent use as lack of usefulness. Zero asks for every delegation the client holds, including the ones backing files an application still has open. There is also no reason NFSD has to reclaim the entire delegation working set on the first sign of memory pressure. Derive the keep count from cl_deleg_count so that each callback asks for one delegation. Both the shrinker and the laundromat re-arm while their condition lasts, so a client with more to give is asked again on the next pass. The Linux client ignores craa_objects_to_keep and returns unused delegations selected from the type mask alone, so the count changes nothing for it. Fixes: 44df6f439a17 ("NFSD: add delegation reaper to react to low memory condition") Cc: stable@vger.kernel.org Reviewed-by: Jeff Layton Link: https://patch.msgid.link/20260817-recall-any-keep-count-v5-4-3b2cffce701e@kernel.org Signed-off-by: Chuck Lever [ sashal: Added missing prerequisites for per-client delegation counting and the directory-delegation callback mask. ] Signed-off-by: Sasha Levin --- fs/nfsd/nfs4state.c | 24 ++++++++++++++++++++---- fs/nfsd/state.h | 2 ++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 3bdde4c1bb8eb..f0a7959401370 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1517,6 +1517,7 @@ hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp) dp->dl_stid.sc_type = SC_TYPE_DELEG; list_add(&dp->dl_perfile, &fp->fi_delegations); list_add(&dp->dl_perclnt, &clp->cl_delegations); + clp->cl_deleg_count++; return 0; } @@ -1548,6 +1549,7 @@ unhash_delegation_locked(struct nfs4_delegation *dp, unsigned short statusmask) ++dp->dl_time; spin_lock(&fp->fi_lock); list_del_init(&dp->dl_perclnt); + dp->dl_stid.sc_client->cl_deleg_count--; list_del_init(&dp->dl_recall_lru); list_del_init(&dp->dl_perfile); spin_unlock(&fp->fi_lock); @@ -7938,6 +7940,7 @@ deleg_reaper(struct nfsd_net *nn) { struct list_head *pos, *next; struct nfs4_client *clp; + unsigned int count; spin_lock(&nn->client_lock); list_for_each_safe(pos, next, &nn->client_lru) { @@ -7947,23 +7950,36 @@ deleg_reaper(struct nfsd_net *nn) continue; if (clp->cl_state != NFSD4_ACTIVE) continue; - if (list_empty(&clp->cl_delegations)) - continue; if (atomic_read(&clp->cl_delegs_in_recall)) continue; if (ktime_get_boottime_seconds() - clp->cl_ra_time < 5) continue; if (clp->cl_cb_state != NFSD4_CB_UP) continue; + /* + * This read races with hash_delegation_locked() and + * unhash_delegation_locked() on other CPUs. A stale + * count only skews the keep value; the next + * laundromat pass sees a more current one. + */ + count = data_race(READ_ONCE(clp->cl_deleg_count)); + if (!count) + continue; if (test_and_set_bit(NFSD4_CALLBACK_RUNNING, &clp->cl_ra->ra_cb.cb_flags)) continue; /* release in nfsd4_cb_recall_any_release */ kref_get(&clp->cl_nfsdfs.cl_ref); clp->cl_ra_time = ktime_get_boottime_seconds(); - clp->cl_ra->ra_keep = 0; + /* + * Ask for a single delegation. Recalling one before it + * is needed costs the client an OPEN when it next + * touches the file. + */ + clp->cl_ra->ra_keep = count - 1; clp->cl_ra->ra_bmval[0] = BIT(RCA4_TYPE_MASK_RDATA_DLG) | - BIT(RCA4_TYPE_MASK_WDATA_DLG); + BIT(RCA4_TYPE_MASK_WDATA_DLG) | + BIT(RCA4_TYPE_MASK_DIR_DLG); trace_nfsd_cb_recall_any(clp->cl_ra); nfsd4_run_cb(&clp->cl_ra->ra_cb); } diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 9661c08b879e8..df35c35890d48 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -610,6 +610,8 @@ struct nfs4_client { unsigned int cl_state; atomic_t cl_delegs_in_recall; + /* Length of cl_delegations, updated under nn->deleg_lock */ + unsigned int cl_deleg_count; struct nfsd4_cb_recall_any *cl_ra; time64_t cl_ra_time; -- 2.53.0