From patchwork Tue Feb 18 15:39:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13980186 X-Patchwork-Delegate: cel@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 3D99F26D5B2 for ; Tue, 18 Feb 2025 15:39:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893182; cv=none; b=mJdir9VmdRn3h8zgdP11QdjuPwgWAPDe+NacRYwhwxg3si8pNWflwEpKsLBMDp5AtKtmcLiABVInJFBQMVmQ8kFsiLa2Uul3xF6IqjEpORqTqVR/RlugVdaRBlT5Lg14oQiFpvYswBxpnlI0JXi34/kaMhfD1bqBUn1FPmR3rSo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893182; c=relaxed/simple; bh=QIonkPUurTbbiJ99MOssvlx5xxbqsLxVStC/S947mHg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=j/CthxFrrrMhlwvnqPqUJQ57A+tDCfwTcTQvEjBtXuIGVTUtU0f+/MSIFQ7WWSiJCJ3QcTJIaGICKQeJDzaXrYDWqH8DZDwi5IWJg/x4J5gKw5UoL9ustQf7Ru6Drq2B0a6MkBeCDd0eZowxynZ53M+Uam95daeqHqj8WtBCA1Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PHLWLyTk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PHLWLyTk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 09487C4CEE9; Tue, 18 Feb 2025 15:39:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739893181; bh=QIonkPUurTbbiJ99MOssvlx5xxbqsLxVStC/S947mHg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PHLWLyTkf2qoRImxs60AF++smuiPhcHwaS7YBQopMTG4R2pmNuHGZOp8fHfXFHGmq JqbUNtgG/KekXZ0qB8gXgbCqYxQxipJsxykTucZDif4zyzLBh0EN76ejmIcYRy8wDx pFZ+dczJmyPab74fivnMRT2H9v/GGebcyUgd0GB01qTV9lYXaehvXqgRpFhYujl67b 1sFESUmyeoOFFrMmhkp0EUmzbfpUg2kd4KfZyPx1yqV3y1NvhE8urOrFdg81litj2/ QW2SZR9uKyH/PweZtbTBFgkgUNY7Kw1zMAkIP8Nfo2LotcfI5NIXB2t2Sz4BrIY1co PRRGkGen0JA3w== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Dave Chinner Subject: [PATCH v2 1/7] nfsd: filecache: remove race handling. Date: Tue, 18 Feb 2025 10:39:31 -0500 Message-ID: <20250218153937.6125-2-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250218153937.6125-1-cel@kernel.org> References: <20250218153937.6125-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: NeilBrown The race that this code tries to protect against is not interesting. The code is problematic as we access the "nf" after we have given our reference to the lru system. While that takes 2+ seconds to free things, it is still poor form. The only interesting race I can find would be with nfsd_file_close_inode_sync(); This is the only place that really doesn't want the file to stay on the LRU when unhashed (which is the direct consequence of the race). However for the race to happen, some other thread must own a reference to a file and be putting it while nfsd_file_close_inode_sync() is trying to close all files for an inode. If this is possible, that other thread could simply call nfsd_file_put() a little bit later and the result would be the same: not all files are closed when nfsd_file_close_inode_sync() completes. If this was really a problem, we would need to wait in close_inode_sync for the other references to be dropped. We probably don't want to do that. So it is best to simply remove this code. Reviewed-by: Jeff Layton Signed-off-by: NeilBrown Signed-off-by: Chuck Lever --- fs/nfsd/filecache.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index fb9b1656a287..909b5bc72bd3 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -370,22 +370,8 @@ nfsd_file_put(struct nfsd_file *nf) if (refcount_dec_not_one(&nf->nf_ref)) return; - /* Try to add it to the LRU. If that fails, decrement. */ - if (nfsd_file_lru_add(nf)) { - /* If it's still hashed, we're done */ - if (test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) { - nfsd_file_schedule_laundrette(); - return; - } - - /* - * We're racing with unhashing, so try to remove it from - * the LRU. If removal fails, then someone else already - * has our reference. - */ - if (!nfsd_file_lru_remove(nf)) - return; - } + if (nfsd_file_lru_add(nf)) + return; } if (refcount_dec_and_test(&nf->nf_ref)) nfsd_file_free(nf); From patchwork Tue Feb 18 15:39:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13980187 X-Patchwork-Delegate: cel@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 C613526D5CC for ; Tue, 18 Feb 2025 15:39:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893182; cv=none; b=CkdoGs5aYpkC91N07DlTeml6YA0/4Z/9fP5H6cWRi/HaG04nLRTTHGzRVpPJVBLodSAsu4RnzfAoprC3OenicirrEdvbJopSgL6Vx8HgUqrVjcN5CeXrf3UR9EUnAS9utKLi4CVl0aQZu5rugw33t6ZZJ6OHahXRFRt2jVLgpXc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893182; c=relaxed/simple; bh=alovUlh+/Om5eQ5X07Twhxxns929XhQ8+5BWBHA5UqA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FGqs5f2k0hWwTUwNmmrWJ9/P+W9tQ6FzJBOi0QoRvVkuJPYJw6uTk8G5abRI5seB8wL7DP7ilemBtA454I6VvhdpDSFFL35Xo8gJFQInctTglDsa3bkvovEf2RlSJ1RFjKTvFW0+rrLMWpc6bWJFXY3YsEWf2OD99EgYJjoOsyQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GJbC0T6+; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GJbC0T6+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E7709C4CEEB; Tue, 18 Feb 2025 15:39:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739893182; bh=alovUlh+/Om5eQ5X07Twhxxns929XhQ8+5BWBHA5UqA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GJbC0T6+UGYPLj4MTCrfHFnuYFhqlXg/6Cw80KBjQsuOZiClOklmVHFOsDhwE7fa+ BCsIUK+Gunk57sR5WaejMfZX0DllIbUSO7auXjEaFyYGslNzlPQO5XbCu4//ZgEIw4 bo4eSErOvCbM/dti/k6nEtumt2Su9L/Qp0+0Uoc/WAlPw9iI6XBNHoW8Oz13Y/L/QI ByVAFKGGUTc6gI6gOzHj3aeJcsSUJD9SXlP6PZsY9Q8qdojpzZFlXukw/c5DAqpJMU GKhkTTbO1QWEUPLwIyvCf9OcVMMUvFXAVMcEVnXZ26UhLKjg0Qkt5s+SEttJEdxSba plWh707eiDBcw== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Dave Chinner , Chuck Lever Subject: [PATCH v2 2/7] NFSD: Re-organize nfsd_file_gc_worker() Date: Tue, 18 Feb 2025 10:39:32 -0500 Message-ID: <20250218153937.6125-3-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250218153937.6125-1-cel@kernel.org> References: <20250218153937.6125-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Chuck Lever Dave opines: IMO, there is no need to do this unnecessary work on every object that is added to the LRU. Changing the gc worker to always run every 2s and check if it has work to do like so: static void nfsd_file_gc_worker(struct work_struct *work) { - nfsd_file_gc(); - if (list_lru_count(&nfsd_file_lru)) - nfsd_file_schedule_laundrette(); + if (list_lru_count(&nfsd_file_lru)) + nfsd_file_gc(); + nfsd_file_schedule_laundrette(); } means that nfsd_file_gc() will be run the same way and have the same behaviour as the current code. When the system it idle, it does a list_lru_count() check every 2 seconds and goes back to sleep. That's going to be pretty much unnoticable on most machines that run NFS servers. Suggested-by: Dave Chinner Signed-off-by: Chuck Lever --- fs/nfsd/filecache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index 909b5bc72bd3..2933cba1e5f4 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -549,9 +549,9 @@ nfsd_file_gc(void) static void nfsd_file_gc_worker(struct work_struct *work) { - nfsd_file_gc(); + nfsd_file_schedule_laundrette(); if (list_lru_count(&nfsd_file_lru)) - nfsd_file_schedule_laundrette(); + nfsd_file_gc(); } static unsigned long From patchwork Tue Feb 18 15:39:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13980188 X-Patchwork-Delegate: cel@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 B2C6A26D5CC for ; Tue, 18 Feb 2025 15:39:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893183; cv=none; b=OSq9eohk6E5cYSqgORxtISSOmIrg5FLh6bWBntf9srqdu+LeBoRMnmNRaj3+74oihnsrc9aW7aqU8NOp1uJJYgCgcQZRgzGIsh16nPjv3R4KdhTWxG+mKUCS5NKmDHD3qnPGsuW5Y93L5CBIfkJEaCNk1BNGLc90B5z0/fi8lfY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893183; c=relaxed/simple; bh=K0kbCsQ5aFEWuQlRov3HGKilBt63WoBIbVoqgj8bdvE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EqDOPgVOD/ZRsF1POvwZLDQbdZC4c8vicC2yvAp+EuI8c6um2eUTA68kDKf7zLRsEQFAUPuP546mWW3XouFBQPnddmFTKc3z3Pg6+V/CGlJHqrDnhTGs/W4wMsnVNzeh7HIfr6HzycA9QMNrer2TnTxFE9y9K1Ek9TDsjdKFHQo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nb2jmZpB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="nb2jmZpB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DFD60C4CEEA; Tue, 18 Feb 2025 15:39:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739893183; bh=K0kbCsQ5aFEWuQlRov3HGKilBt63WoBIbVoqgj8bdvE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nb2jmZpB1MQiw95CY370h2oIkFlmtm5MMFBfKcmr8P2jm0/cezwBP5/3ThZ+/VInd 6UN5lGO7F8U61uZO50rejbkUgB51vr3HcuedqrzHf96A1jbwB9g8QbNfp/n4nULnfD xW7tDdUXPPypMqT0k56ZM4t2S0aiUKxd0mLQl6bQyRopi7A7MzhGaBt5sgOpaNevd2 fmsTK7PD2b9UEVXrfaNwMKgNjTnbtJF1Fw9dLZ2yfXFcwKDYzkDqF5dxD6rlBePtKJ p97FSuaygrDHK/rW/ZdBy7+YVQEr/zlo9Yce7kYG6lf/ySdeE6yb3gGyOWz1BzA9vI FuoiM0G/Euwyw== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Dave Chinner Subject: [PATCH v2 3/7] nfsd: filecache: use nfsd_file_dispose_list() in nfsd_file_close_inode_sync() Date: Tue, 18 Feb 2025 10:39:33 -0500 Message-ID: <20250218153937.6125-4-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250218153937.6125-1-cel@kernel.org> References: <20250218153937.6125-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: NeilBrown nfsd_file_close_inode_sync() contains an exact copy of nfsd_file_dispose_list(). This patch removes that copy and calls nfsd_file_dispose_list() instead. Reviewed-by: Jeff Layton Signed-off-by: NeilBrown Signed-off-by: Chuck Lever --- fs/nfsd/filecache.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index 2933cba1e5f4..143b5993a437 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -672,17 +672,12 @@ nfsd_file_close_inode(struct inode *inode) void nfsd_file_close_inode_sync(struct inode *inode) { - struct nfsd_file *nf; LIST_HEAD(dispose); trace_nfsd_file_close(inode); nfsd_file_queue_for_close(inode, &dispose); - while (!list_empty(&dispose)) { - nf = list_first_entry(&dispose, struct nfsd_file, nf_gc); - list_del_init(&nf->nf_gc); - nfsd_file_free(nf); - } + nfsd_file_dispose_list(&dispose); } static int From patchwork Tue Feb 18 15:39:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13980189 X-Patchwork-Delegate: cel@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 C745126D5CC for ; Tue, 18 Feb 2025 15:39:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893185; cv=none; b=TnXp3lTHNbdE/g8thi2hz03K8L0bwtgKfjrtc4k2qdxlDw2kD8Jh7ePxRr93C4WZCwAOByOydZocf2BwkxQk4RxPEjg4djdKUW7mZu/SYNek7jCxDWsIHLsRU0tR+MXGBtA3Eo7mhI7J+hV572lixPq+GjlbWtMVBwiRf7q4og0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893185; c=relaxed/simple; bh=1k2PgSxTzE2sJtExkePSUbe2IWZcR1pB82e08Xr8iSo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TmpMxBfF0mgCnhLZkWkfluWWfW1G5yXO9Svbr+tv/gE8XYCs0f2fLzjCvJAPyjxHRD/jRrZ677l8x4hTyvru4lfiwVNpjH1CCDNmUSEZGDWS8xkXqZgcy7wMFoRzD068ZZcGr9otojVc6h/rQt5GXshsmWEp9bbjc/tVqHdMack= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VtRk5xnB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VtRk5xnB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C668AC4CEE2; Tue, 18 Feb 2025 15:39:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739893184; bh=1k2PgSxTzE2sJtExkePSUbe2IWZcR1pB82e08Xr8iSo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VtRk5xnBtWBBfrzspWhA8xedoj1iyiHTRPnzGYk+Fc4vmTdlJiMsiF9Mbda/tvpvT Tuk1HyGmRW5zDZdRUBKygsb3CfjRPlkaQkGFr1d72tD4Xy2uL9XbBixtKsZVlAiwNf FDBmP3cOlPwn1JJg5XJRZTqSUhOZ6/cvtVlML+T4YIf0EDOGNZ3C5P4rvnlcITFk6N ianyCacg3pYDa/GESDZXCCDjpBqhSOr0J+mPqL6Xi75PmXDEBFmqpToBZphrV3a2Q3 A3XYdoMRftmUA+FxEyle1UgX9lwxcZmrU6GRvMQknAu0jLEegrHsYjVcjEs2cPl393 zA5jLObHyki3w== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Dave Chinner Subject: [PATCH v2 4/7] nfsd: filecache: use list_lru_walk_node() in nfsd_file_gc() Date: Tue, 18 Feb 2025 10:39:34 -0500 Message-ID: <20250218153937.6125-5-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250218153937.6125-1-cel@kernel.org> References: <20250218153937.6125-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: NeilBrown list_lru_walk() is only useful when the aim is to remove all elements from the list_lru. It will repeatedly visit rotated elements of the first per-node sublist before proceeding to subsequent sublists. This patch changes nfsd_file_gc() to use list_lru_walk_node() and list_lru_count_node() on each NUMA node. Signed-off-by: NeilBrown Reviewed-by: Jeff Layton Signed-off-by: Chuck Lever --- fs/nfsd/filecache.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index 143b5993a437..747929c8c0d5 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -537,11 +537,16 @@ nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru, static void nfsd_file_gc(void) { + unsigned long ret = 0; LIST_HEAD(dispose); - unsigned long ret; + int nid; - ret = list_lru_walk(&nfsd_file_lru, nfsd_file_lru_cb, - &dispose, list_lru_count(&nfsd_file_lru)); + for_each_node_state(nid, N_NORMAL_MEMORY) { + unsigned long nr = list_lru_count_node(&nfsd_file_lru, nid); + + ret += list_lru_walk_node(&nfsd_file_lru, nid, nfsd_file_lru_cb, + &dispose, &nr); + } trace_nfsd_file_gc_removed(ret, list_lru_count(&nfsd_file_lru)); nfsd_file_dispose_list_delayed(&dispose); } From patchwork Tue Feb 18 15:39:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13980190 X-Patchwork-Delegate: cel@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 C73EA26B968 for ; Tue, 18 Feb 2025 15:39:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893185; cv=none; b=X4mDuRjfEm2K408C1ivtWdVManrz5K54RIHsqIIxdhBSNWXZe1AIr5vz2dspadWSbFoTr19Hh28VDAyRBZGwqDfSvmMC2x4G8QmWnkN9eP/I0GxiKuH09m8zOq82guA4VQ93q827XcXSx96H1GYpH9lP3cYZxXCAqko3yg0PgFY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893185; c=relaxed/simple; bh=qHiS4IzCVpGM4RTkqp/s/x5lqhU+jKs59ky5QPy9kQA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ASkafyCorwWF5qmcvHgjpn/g+r2Dg5yX3WJhw6ZaQBLSh92E0q7amjfdMMOExv7N9ZmA/LY7pX4ekotcnfJ+NZ8wYe1MkJtmHAqFCS9UVFQQh4hb5fkFHDKWBKxgGybv0hZ5qeqBciR7zYBLuG3wQ5ERh7ILyq6tt6soGWjkr1g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DwumJEW8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DwumJEW8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AEEDAC4CEE7; Tue, 18 Feb 2025 15:39:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739893185; bh=qHiS4IzCVpGM4RTkqp/s/x5lqhU+jKs59ky5QPy9kQA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DwumJEW8BDuN1OrP807OTm9+HPg+6tz4hJcl2oiUakhDutf3ccHa8WCKkja6Ww4Vk kZYgIQDyLAPTVrDWltqinEhUAgdPUM0jZTgcS0kwarnrZsYj+cbgQwsHQx/CQY6s6G aQ5A8f7UdCZcnby6FxaBdfFalia9RYd+HsVau9rAMwlhAlXGzVah+GXvIlGtqOLEyl cXBhDpRCRIGzmpaYMt5g/Qq9eNz5Senv97Nr2VuTu55VGrHQsCfWYzDUcTGakD8FT2 yiT9Xa7aGpACT0arTY+fkvclC+c4WSTtAgouNUAi77S/7QRYei1CC71x3H/q0RjQTp aIfTEoFNL456Q== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Dave Chinner Subject: [PATCH v2 5/7] nfsd: filecache: introduce NFSD_FILE_RECENT Date: Tue, 18 Feb 2025 10:39:35 -0500 Message-ID: <20250218153937.6125-6-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250218153937.6125-1-cel@kernel.org> References: <20250218153937.6125-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: NeilBrown The filecache lru is walked in 2 circumstances for 2 different reasons. 1/ When called from the shrinker we want to discard the first few entries on the list, ignoring any with NFSD_FILE_REFERENCED set because they should really be at the end of the LRU as they have been referenced recently. So those ones are ROTATED. 2/ When called from the nfsd_file_gc() timer function we want to discard anything that hasn't been used since before the previous call, and mark everything else as unused at this point in time. Using the same flag for both of these can result in some unexpected outcomes. If the shrinker callback clears NFSD_FILE_REFERENCED then nfsd_file_gc() will think the file hasn't been used in a while, while really it has. I think it is easier to reason about the behaviour if we instead have two flags. NFSD_FILE_REFERENCED means "this should be at the end of the LRU, please put it there when convenient" NFSD_FILE_RECENT means "this has been used recently - since the last run of nfsd_file_gc() When either caller finds an NFSD_FILE_REFERENCED entry, that entry should be moved to the end of the LRU and the flag cleared. This can safely happen at any time. The actual order on the lru might not be strictly least-recently-used, but that is normal for linux lrus. The shrinker callback can ignore the "recent" flag. If it ends up freeing something that is "recent" that simply means that memory pressure is sufficient to limit the acceptable cache age to less than the nfsd_file_gc frequency. The gc callback should primarily focus on NFSD_FILE_RECENT. It should free everything that doesn't have this flag set, and should clear the flag on everything else. When it clears the flag it is convenient to clear the "REFERENCED" flag and move to the end of the LRU too. With this, calls from the shrinker do not prematurely age files. It will focus only on freeing those that are least recently used. Signed-off-by: NeilBrown Reviewed-by: Jeff Layton Signed-off-by: Chuck Lever --- fs/nfsd/filecache.c | 22 ++++++++++++++++++++-- fs/nfsd/filecache.h | 1 + fs/nfsd/trace.h | 3 +++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index 747929c8c0d5..0d621833a9f2 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -319,10 +319,10 @@ nfsd_file_check_writeback(struct nfsd_file *nf) mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK); } - static bool nfsd_file_lru_add(struct nfsd_file *nf) { set_bit(NFSD_FILE_REFERENCED, &nf->nf_flags); + set_bit(NFSD_FILE_RECENT, &nf->nf_flags); if (list_lru_add_obj(&nfsd_file_lru, &nf->nf_lru)) { trace_nfsd_file_lru_add(nf); return true; @@ -534,6 +534,24 @@ nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru, return LRU_REMOVED; } +static enum lru_status +nfsd_file_gc_cb(struct list_head *item, struct list_lru_one *lru, + void *arg) +{ + struct nfsd_file *nf = list_entry(item, struct nfsd_file, nf_lru); + + if (test_and_clear_bit(NFSD_FILE_RECENT, &nf->nf_flags)) { + /* + * "REFERENCED" really means "should be at the end of the + * LRU. As we are putting it there we can clear the flag. + */ + clear_bit(NFSD_FILE_REFERENCED, &nf->nf_flags); + trace_nfsd_file_gc_aged(nf); + return LRU_ROTATE; + } + return nfsd_file_lru_cb(item, lru, arg); +} + static void nfsd_file_gc(void) { @@ -544,7 +562,7 @@ nfsd_file_gc(void) for_each_node_state(nid, N_NORMAL_MEMORY) { unsigned long nr = list_lru_count_node(&nfsd_file_lru, nid); - ret += list_lru_walk_node(&nfsd_file_lru, nid, nfsd_file_lru_cb, + ret += list_lru_walk_node(&nfsd_file_lru, nid, nfsd_file_gc_cb, &dispose, &nr); } trace_nfsd_file_gc_removed(ret, list_lru_count(&nfsd_file_lru)); diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h index d5db6b34ba30..de5b8aa7fcb0 100644 --- a/fs/nfsd/filecache.h +++ b/fs/nfsd/filecache.h @@ -38,6 +38,7 @@ struct nfsd_file { #define NFSD_FILE_PENDING (1) #define NFSD_FILE_REFERENCED (2) #define NFSD_FILE_GC (3) +#define NFSD_FILE_RECENT (4) unsigned long nf_flags; refcount_t nf_ref; unsigned char nf_may; diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h index 49bbd26ffcdb..d93573504fa4 100644 --- a/fs/nfsd/trace.h +++ b/fs/nfsd/trace.h @@ -1050,6 +1050,7 @@ DEFINE_CLID_EVENT(confirmed_r); { 1 << NFSD_FILE_HASHED, "HASHED" }, \ { 1 << NFSD_FILE_PENDING, "PENDING" }, \ { 1 << NFSD_FILE_REFERENCED, "REFERENCED" }, \ + { 1 << NFSD_FILE_RECENT, "RECENT" }, \ { 1 << NFSD_FILE_GC, "GC" }) DECLARE_EVENT_CLASS(nfsd_file_class, @@ -1328,6 +1329,7 @@ DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_lru_del_disposed); DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_in_use); DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_writeback); DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_referenced); +DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_aged); DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_disposed); DECLARE_EVENT_CLASS(nfsd_file_lruwalk_class, @@ -1357,6 +1359,7 @@ DEFINE_EVENT(nfsd_file_lruwalk_class, name, \ TP_ARGS(removed, remaining)) DEFINE_NFSD_FILE_LRUWALK_EVENT(nfsd_file_gc_removed); +DEFINE_NFSD_FILE_LRUWALK_EVENT(nfsd_file_gc_recent); DEFINE_NFSD_FILE_LRUWALK_EVENT(nfsd_file_shrinker_removed); TRACE_EVENT(nfsd_file_close, From patchwork Tue Feb 18 15:39:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13980191 X-Patchwork-Delegate: cel@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 65E9226E14C for ; Tue, 18 Feb 2025 15:39:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893186; cv=none; b=N1A+SF6CyR/q8q8JMsxxOtwevuycML6orZWTbFipeLrK1ObYqz4pZKKzdzaPQjbIjCbwKFEwqFqDzpZqWzbjA60nVTdC4WntoJsqRayqG58RpAsNkJ8/BtrcSEaowijNg/iVnfDrNG542GybN43mpcJnMwWFL7gRWOJQO2APJVg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893186; c=relaxed/simple; bh=KgD8olzpy3uRadg0WZIMzpp3j/wHnbKkAWaFarN6yuU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TbV7Bfw70Wpe2F3R6PwmIdDgGp1+R5SrrkDqSZFmasSwdx/RZKIprZauBYY462EVnl0ZtTljknXpb+XwQ7gg/xq1svzxO25EIf9K2n/f2Jb66wlUyKSTiCm1crTpgvgMQ8M8t38QEitRvbMKKVJoqqmjpVUath2ynJEHsr3b3cU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uhxmGDTm; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uhxmGDTm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 95AEBC4CEEA; Tue, 18 Feb 2025 15:39:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739893186; bh=KgD8olzpy3uRadg0WZIMzpp3j/wHnbKkAWaFarN6yuU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uhxmGDTmLDuFfzfVx11C9f2dK4XLJyz7Aiapjg2wRium4DUz1IYRWoh/lD1Bd/V09 aAHIKzVgsVGvcWfJeASbB9aY75h5tHK2rHoSyrYQaeJu4y5kh6J8q2uON4b4sLoS4x fwjdKc4d+Kd0XKSb9Ey8AJjMU24UYKkCfivOhzTHvix6FWlNvV/cU5jtXvY1NdUobF p1wN4962ccpEv8b9MGC/H9i06CUWh4lo6nhOWiqMr0lTwyaSg/oNiJy/0drHeSmVfh oYGvtEsetznByongR0aGndib95GruQQbk5pTZBmry8FJUK0wADSvKUicGtvsF7G/yE E9mVkyX80Hfmw== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Dave Chinner Subject: [PATCH v2 6/7] nfsd: filecache: don't repeatedly add/remove files on the lru list Date: Tue, 18 Feb 2025 10:39:36 -0500 Message-ID: <20250218153937.6125-7-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250218153937.6125-1-cel@kernel.org> References: <20250218153937.6125-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: NeilBrown There is no need to remove a file from the lru every time we access it, and then add it back. It is sufficient to set the REFERENCED flag every time we put the file. The order in the lru of REFERENCED files is largely irrelevant as they will all be moved to the end. With this patch, files are added only when they are allocated (if want_gc) and they are removed only by the list_lru_(shrink_)walk callback or when forcibly removing a file. This should reduce contention on the list_lru spinlock(s) and reduce memory traffic a little. Signed-off-by: NeilBrown Signed-off-by: Chuck Lever Reviewed-by: Jeff Layton --- fs/nfsd/filecache.c | 47 ++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index 0d621833a9f2..56935349f0e4 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -319,15 +319,14 @@ nfsd_file_check_writeback(struct nfsd_file *nf) mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK); } -static bool nfsd_file_lru_add(struct nfsd_file *nf) +static void nfsd_file_lru_add(struct nfsd_file *nf) { - set_bit(NFSD_FILE_REFERENCED, &nf->nf_flags); - set_bit(NFSD_FILE_RECENT, &nf->nf_flags); - if (list_lru_add_obj(&nfsd_file_lru, &nf->nf_lru)) { + refcount_inc(&nf->nf_ref); + if (list_lru_add_obj(&nfsd_file_lru, &nf->nf_lru)) trace_nfsd_file_lru_add(nf); - return true; - } - return false; + else + WARN_ON(1); + nfsd_file_schedule_laundrette(); } static bool nfsd_file_lru_remove(struct nfsd_file *nf) @@ -363,16 +362,10 @@ nfsd_file_put(struct nfsd_file *nf) if (test_bit(NFSD_FILE_GC, &nf->nf_flags) && test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) { - /* - * If this is the last reference (nf_ref == 1), then try to - * transfer it to the LRU. - */ - if (refcount_dec_not_one(&nf->nf_ref)) - return; - - if (nfsd_file_lru_add(nf)) - return; + set_bit(NFSD_FILE_REFERENCED, &nf->nf_flags); + set_bit(NFSD_FILE_RECENT, &nf->nf_flags); } + if (refcount_dec_and_test(&nf->nf_ref)) nfsd_file_free(nf); } @@ -516,13 +509,12 @@ nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru, } /* - * Put the reference held on behalf of the LRU. If it wasn't the last - * one, then just remove it from the LRU and ignore it. + * Put the reference held on behalf of the LRU if it is the last + * reference, else rotate. */ - if (!refcount_dec_and_test(&nf->nf_ref)) { + if (!refcount_dec_if_one(&nf->nf_ref)) { trace_nfsd_file_gc_in_use(nf); - list_lru_isolate(lru, &nf->nf_lru); - return LRU_REMOVED; + return LRU_ROTATE; } /* Refcount went to zero. Unhash it and queue it to the dispose list */ @@ -1062,16 +1054,8 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net, nf = nfsd_file_lookup_locked(net, current_cred(), inode, need, want_gc); rcu_read_unlock(); - if (nf) { - /* - * If the nf is on the LRU then it holds an extra reference - * that must be put if it's removed. It had better not be - * the last one however, since we should hold another. - */ - if (nfsd_file_lru_remove(nf)) - refcount_dec(&nf->nf_ref); + if (nf) goto wait_for_construction; - } new = nfsd_file_alloc(net, inode, need, want_gc); if (!new) { @@ -1165,6 +1149,9 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net, */ if (status != nfs_ok || inode->i_nlink == 0) nfsd_file_unhash(nf); + else if (want_gc) + nfsd_file_lru_add(nf); + clear_and_wake_up_bit(NFSD_FILE_PENDING, &nf->nf_flags); if (status == nfs_ok) goto out; From patchwork Tue Feb 18 15:39:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13980192 X-Patchwork-Delegate: cel@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 50082262811 for ; Tue, 18 Feb 2025 15:39:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893187; cv=none; b=k/3mQGomoJhGkFW6G3WGxE9G6IHQeuX80UNbvqbEM3+wAtr7+pSfC5F+DRcDHm2tRcxay5ai3BYRdWF2a3jtR9im7u6OurgmWmdnuCucnKPmrQXJw0U+D2zHdvIsz0IXni/U0lrMz5rcQOSkB0i7jLJRykv8oXQQratmkwIjAe0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739893187; c=relaxed/simple; bh=WCmHZN7hoYJGUWLVypvb4UKXeYsh5UC0n/+MvyCK65E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Hd6UPukFJQEnLB+ya1OAPJRRaFSrnLTPZ0/GLfGt9Tze3zBnRic79B1LV9MiLuqH5YSV02whG7/p7NX7y4OSbe8K0qndDplvhctFJpR47IwMzExkYj1usc64DcdjsgRDxlIVvU8GaGFIkWW1I1cLza7b/Oi/PT8JQehcgL0BedQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VHdKgL41; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VHdKgL41" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 82D76C4CEE7; Tue, 18 Feb 2025 15:39:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739893187; bh=WCmHZN7hoYJGUWLVypvb4UKXeYsh5UC0n/+MvyCK65E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VHdKgL41CjaNGjqnpxd/gRtuMWlyzJ+xqr7o+qM4ayt8lP3uqTpi9+qmlZ6eKYkjc /dIlV9W8YXR5EgS8jrohV5yVTBVgocD1WZlg9jPh9aqgZf6I8rKU+IMRFJovci9W3I pF2soHucegoCGelkytnQrX5OsLtxBaRNr9DAg0dPQZ5NJhA34UjbJw2EYbeWcitRz9 qZtPTQcKEXZgM9igGVkidmlicf62MGy/6LAJDVF9goSGHDm4fli/JJ6+YPjc4iGVT2 hmpGN8VQ1wF8M2Q5p/qvgS9DhsipAUSsy2F8nQZ5NuFzdV1TBwV0AXNx+oNgZlExsU lcByvzUTUIUtQ== From: cel@kernel.org To: Neil Brown , Jeff Layton , Olga Kornievskaia , Dai Ngo , Tom Talpey Cc: , Dave Chinner Subject: [PATCH v2 7/7] nfsd: filecache: drop the list_lru lock during lock gc scans Date: Tue, 18 Feb 2025 10:39:37 -0500 Message-ID: <20250218153937.6125-8-cel@kernel.org> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250218153937.6125-1-cel@kernel.org> References: <20250218153937.6125-1-cel@kernel.org> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: NeilBrown Under a high NFSv3 load with lots of different files being accessed, the LRU list of garbage-collectable files can become quite long. Asking list_lru_scan_node() to scan the whole list can result in a long period during which a spinlock is held, blocking the addition of new LRU items. So ask list_lru_scan_node() to scan only a few entries at a time, and repeat until the scan is complete. If the shrinker runs between two consecutive calls of list_lru_scan_node() it could invalidate the "remaining" counter which could lead to premature freeing. So add a spinlock to avoid that. Signed-off-by: NeilBrown Signed-off-by: Chuck Lever Reviewed-by: Jeff Layton --- fs/nfsd/filecache.c | 27 ++++++++++++++++++++++++--- fs/nfsd/filecache.h | 6 ++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index 56935349f0e4..9a41ccfc2df6 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -544,6 +544,13 @@ nfsd_file_gc_cb(struct list_head *item, struct list_lru_one *lru, return nfsd_file_lru_cb(item, lru, arg); } +/* If the shrinker runs between calls to list_lru_walk_node() in + * nfsd_file_gc(), the "remaining" count will be wrong. This could + * result in premature freeing of some files. This may not matter much + * but is easy to fix with this spinlock which temporarily disables + * the shrinker. + */ +static DEFINE_SPINLOCK(nfsd_gc_lock); static void nfsd_file_gc(void) { @@ -551,12 +558,22 @@ nfsd_file_gc(void) LIST_HEAD(dispose); int nid; + spin_lock(&nfsd_gc_lock); for_each_node_state(nid, N_NORMAL_MEMORY) { - unsigned long nr = list_lru_count_node(&nfsd_file_lru, nid); + unsigned long remaining = list_lru_count_node(&nfsd_file_lru, nid); - ret += list_lru_walk_node(&nfsd_file_lru, nid, nfsd_file_gc_cb, - &dispose, &nr); + while (remaining > 0) { + unsigned long nr = min(remaining, NFSD_FILE_GC_BATCH); + + remaining -= nr; + ret += list_lru_walk_node(&nfsd_file_lru, nid, nfsd_file_gc_cb, + &dispose, &nr); + if (nr) + /* walk aborted early */ + remaining = 0; + } } + spin_unlock(&nfsd_gc_lock); trace_nfsd_file_gc_removed(ret, list_lru_count(&nfsd_file_lru)); nfsd_file_dispose_list_delayed(&dispose); } @@ -581,8 +598,12 @@ nfsd_file_lru_scan(struct shrinker *s, struct shrink_control *sc) LIST_HEAD(dispose); unsigned long ret; + if (!spin_trylock(&nfsd_gc_lock)) + return SHRINK_STOP; + ret = list_lru_shrink_walk(&nfsd_file_lru, sc, nfsd_file_lru_cb, &dispose); + spin_unlock(&nfsd_gc_lock); trace_nfsd_file_shrinker_removed(ret, list_lru_count(&nfsd_file_lru)); nfsd_file_dispose_list_delayed(&dispose); return ret; diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h index de5b8aa7fcb0..5865f9c72712 100644 --- a/fs/nfsd/filecache.h +++ b/fs/nfsd/filecache.h @@ -3,6 +3,12 @@ #include +/* + * Limit the time that the list_lru_one lock is held during + * an LRU scan. + */ +#define NFSD_FILE_GC_BATCH (16UL) + /* * This is the fsnotify_mark container that nfsd attaches to the files that it * is holding open. Note that we have a separate refcount here aside from the