summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrond Myklebust <trondmy@gmail.com>2020-01-27 09:58:19 -0500
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2020-02-03 16:35:07 -0500
commit10717f45639f6c1bc27b56405252c3a027406d92 (patch)
tree1e662a1cf98f5fbef1a540f53732bd3facc1afea
parentd2269ea14ebd2a73f291d6b3a7a7d320ec00270c (diff)
NFSv4: Limit the total number of cached delegations
Delegations can be expensive to return, and can cause scalability issues for the server. Let's therefore try to limit the number of inactive delegations we hold. Once the number of delegations is above a certain threshold, start to return them on close. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r--fs/nfs/delegation.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index a777b3d0e720..4a841071d8a7 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -25,7 +25,10 @@
#include "internal.h"
#include "nfs4trace.h"
+#define NFS_DEFAULT_DELEGATION_WATERMARK (5000U)
+
static atomic_long_t nfs_active_delegations;
+static unsigned nfs_delegation_watermark = NFS_DEFAULT_DELEGATION_WATERMARK;
static void __nfs_free_delegation(struct nfs_delegation *delegation)
{
@@ -676,7 +679,8 @@ void nfs4_inode_return_delegation_on_close(struct inode *inode)
delegation = nfs4_get_valid_delegation(inode);
if (!delegation)
goto out;
- if (test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags)) {
+ if (test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) ||
+ atomic_long_read(&nfs_active_delegations) >= nfs_delegation_watermark) {
spin_lock(&delegation->lock);
if (delegation->inode &&
list_empty(&NFS_I(inode)->open_files) &&
@@ -1365,3 +1369,5 @@ out:
rcu_read_unlock();
return ret;
}
+
+module_param_named(delegation_watermark, nfs_delegation_watermark, uint, 0644);