Received: by 2002:a05:7412:419a:b0:f3:1519:9f41 with SMTP id i26csp4169981rdh; Tue, 28 Nov 2023 14:00:01 -0800 (PST) X-Google-Smtp-Source: AGHT+IEAorVTWWuJGjyRVCJA7eOYHCh8y4crOCmliGZLH7ESgHTE7OiCAbgHbXzHOLwrj2bD881C X-Received: by 2002:a05:622a:4d91:b0:423:9f29:e000 with SMTP id ff17-20020a05622a4d9100b004239f29e000mr17323047qtb.67.1701208801078; Tue, 28 Nov 2023 14:00:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701208801; cv=none; d=google.com; s=arc-20160816; b=lM/no1E664v8EPCmIZVsc0TALQ4v54TF+JPGmMR4e4rHwH7FLJZxVOGwjfj0IFY328 PV3Dw6qGlZAPVFQ5S5J7hVliEQQ2tnuT6pq4ztnkgX7WB0yQxzcf6jJvM8CN4O1nG6mR FMRjMXeO9t76LJjZtLJpYK1D6MD9lHtv/Ajwp+jPbyCBD37ZxKISwYG/5WwYpz/TAOno gU/o5sct0W6lFRdY19AvtQt5OBLO7VeH90L+Lmp5vWolR6YEzwh+Dz/f+5lDusOjJnkw 6IQbaCVf09ELwoZZaQ4054P/lFgYpyyiiE0+OU+Fp8yHmWK54SPRfvvWJuijrYIQqaAK aEfQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:user-agent:references:in-reply-to :message-id:date:cc:to:from:subject:dkim-signature; bh=eULo6fuJZmNWSedg8shTusVHI2C6nSfWV54vi+3rOeU=; fh=xkJJ9G/tfqFUcIeP82drScMuFzbH6I4bp3/iFRpdd9E=; b=WTOeHy2VvGNM53x4oU9Pn+W6gH2VWXyevhuXxe8/8tbtFDIQLskmZyJy3vTF2I0QWm kRjMT66yBPXyMYqMb+uR9EwM+b26aoNFxbalCNcWFcKyUSST6i2320QSn+CoQNvic8gV o1DAypRYx5l5sHl+/x1WC8zRr4hfvAufxkR0sw9h6xrTafYc9CpABhgNoEHQZI2b8KOr 60OJ9JKRpGIF2R/uYZfUHnqkTqohiJcs8Li6QDvbRTTQEyszmTX7bX545mSWtBqN9A9/ 5aN6Wr01KeShkHFAFOhxzV2eSWHdOAouEWrLJcRydZiMvMBZCj1EKHSuxXdxaDksNuas X9Zw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=Z0nloBYl; spf=pass (google.com: domain of linux-nfs+bounces-143-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-nfs+bounces-143-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id c2-20020a05622a024200b00418196f9d1asi12598736qtx.546.2023.11.28.14.00.00 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Nov 2023 14:00:01 -0800 (PST) Received-SPF: pass (google.com: domain of linux-nfs+bounces-143-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=Z0nloBYl; spf=pass (google.com: domain of linux-nfs+bounces-143-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-nfs+bounces-143-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id C0F151C209AB for ; Tue, 28 Nov 2023 22:00:00 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8171F42A8B; Tue, 28 Nov 2023 21:59:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Z0nloBYl" X-Original-To: linux-nfs@vger.kernel.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 6274544390; Tue, 28 Nov 2023 21:59:59 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0CAD1C433C7; Tue, 28 Nov 2023 21:59:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701208799; bh=H5pH+G0/mC26D2UISmtxczw1Tof4hLeZk9aPvkUQ93I=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=Z0nloBYltk3AiBXK5remPzYzVDx/Zrs8mRzWw4p19M4oMQIfdb4TZHt5V3nvqkEpS DVCfapD4gQYNae9PoyjT5H2L9hliL72jKdMmmaP9YcW+pzKvvwO/laLexAK40klqMD 83XjryL4EylSBDH8dPKFjROgKT2vxZCVKeU50ljhH5lsMHBPNnM8lH1pLipXv5Bb0Y aSoIH7gvb690WqtUdjou7HmvJH/T9HSXrrE7ngz8tGFS7gWD+HkKFiJEFPecBFEBnZ TLNLjXLq1Z0fePgj+Lk4lhhY3FnXdQn1mQrT4wwn34z3+ElLA7eNSNGolPZmwovXNF Bw0H60Ii82HHQ== Subject: [PATCH 4/8] NFSD: Refactor the duplicate reply cache shrinker From: Chuck Lever To: stable@vger.kernel.org Cc: linux-nfs@vger.kernel.org Date: Tue, 28 Nov 2023 16:59:58 -0500 Message-ID: <170120879800.1515.15350509894290203882.stgit@klimt.1015granger.net> In-Reply-To: <170120874713.1515.13712791731008720729.stgit@klimt.1015granger.net> References: <170120874713.1515.13712791731008720729.stgit@klimt.1015granger.net> User-Agent: StGit/1.5 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 From: Chuck Lever [ Upstream commit c135e1269f34dfdea4bd94c11060c83a3c0b3c12 ] Avoid holding the bucket lock while freeing cache entries. This change also caps the number of entries that are freed when the shrinker calls to reduce the shrinker's impact on the cache's effectiveness. Reviewed-by: Jeff Layton Signed-off-by: Chuck Lever --- fs/nfsd/nfscache.c | 82 +++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index 9dfa2c03b712..8aab82ca798b 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c @@ -310,68 +310,64 @@ nfsd_prune_bucket_locked(struct nfsd_net *nn, struct nfsd_drc_bucket *b, } } -static long prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn, - unsigned int max) +/** + * nfsd_reply_cache_count - count_objects method for the DRC shrinker + * @shrink: our registered shrinker context + * @sc: garbage collection parameters + * + * Returns the total number of entries in the duplicate reply cache. To + * keep things simple and quick, this is not the number of expired entries + * in the cache (ie, the number that would be removed by a call to + * nfsd_reply_cache_scan). + */ +static unsigned long +nfsd_reply_cache_count(struct shrinker *shrink, struct shrink_control *sc) { - struct svc_cacherep *rp, *tmp; - long freed = 0; + struct nfsd_net *nn = container_of(shrink, + struct nfsd_net, nfsd_reply_cache_shrinker); - list_for_each_entry_safe(rp, tmp, &b->lru_head, c_lru) { - /* - * Don't free entries attached to calls that are still - * in-progress, but do keep scanning the list. - */ - if (rp->c_state == RC_INPROG) - continue; - if (atomic_read(&nn->num_drc_entries) <= nn->max_drc_entries && - time_before(jiffies, rp->c_timestamp + RC_EXPIRE)) - break; - nfsd_reply_cache_free_locked(b, rp, nn); - if (max && freed++ > max) - break; - } - return freed; + return atomic_read(&nn->num_drc_entries); } -/* - * Walk the LRU list and prune off entries that are older than RC_EXPIRE. - * Also prune the oldest ones when the total exceeds the max number of entries. +/** + * nfsd_reply_cache_scan - scan_objects method for the DRC shrinker + * @shrink: our registered shrinker context + * @sc: garbage collection parameters + * + * Free expired entries on each bucket's LRU list until we've released + * nr_to_scan freed objects. Nothing will be released if the cache + * has not exceeded it's max_drc_entries limit. + * + * Returns the number of entries released by this call. */ -static long -prune_cache_entries(struct nfsd_net *nn) +static unsigned long +nfsd_reply_cache_scan(struct shrinker *shrink, struct shrink_control *sc) { + struct nfsd_net *nn = container_of(shrink, + struct nfsd_net, nfsd_reply_cache_shrinker); + unsigned long freed = 0; + LIST_HEAD(dispose); unsigned int i; - long freed = 0; for (i = 0; i < nn->drc_hashsize; i++) { struct nfsd_drc_bucket *b = &nn->drc_hashtbl[i]; if (list_empty(&b->lru_head)) continue; + spin_lock(&b->cache_lock); - freed += prune_bucket(b, nn, 0); + nfsd_prune_bucket_locked(nn, b, 0, &dispose); spin_unlock(&b->cache_lock); - } - return freed; -} -static unsigned long -nfsd_reply_cache_count(struct shrinker *shrink, struct shrink_control *sc) -{ - struct nfsd_net *nn = container_of(shrink, - struct nfsd_net, nfsd_reply_cache_shrinker); + freed += nfsd_cacherep_dispose(&dispose); + if (freed > sc->nr_to_scan) + break; + } - return atomic_read(&nn->num_drc_entries); + trace_nfsd_drc_gc(nn, freed); + return freed; } -static unsigned long -nfsd_reply_cache_scan(struct shrinker *shrink, struct shrink_control *sc) -{ - struct nfsd_net *nn = container_of(shrink, - struct nfsd_net, nfsd_reply_cache_shrinker); - - return prune_cache_entries(nn); -} /* * Walk an xdr_buf and get a CRC for at most the first RC_CSUMLEN bytes */