NFSv4: Add accounting for the number of active delegations held
authorTrond Myklebust <trondmy@gmail.com>
Mon, 27 Jan 2020 14:58:18 +0000 (09:58 -0500)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Mon, 3 Feb 2020 21:35:07 +0000 (16:35 -0500)
In order to better manage our delegation caching, add a counter
to track the number of active delegations.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/delegation.c

index 90e50f32f3e0ec5d7510d467e8d13b4282bf5015..a777b3d0e7204903ffd431ce997976ea3bb3ec6e 100644 (file)
 #include "internal.h"
 #include "nfs4trace.h"
 
-static void nfs_free_delegation(struct nfs_delegation *delegation)
+static atomic_long_t nfs_active_delegations;
+
+static void __nfs_free_delegation(struct nfs_delegation *delegation)
 {
        put_cred(delegation->cred);
        delegation->cred = NULL;
        kfree_rcu(delegation, rcu);
 }
 
+static void nfs_mark_delegation_revoked(struct nfs_delegation *delegation)
+{
+       if (!test_and_set_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
+               delegation->stateid.type = NFS4_INVALID_STATEID_TYPE;
+               atomic_long_dec(&nfs_active_delegations);
+       }
+}
+
+static void nfs_free_delegation(struct nfs_delegation *delegation)
+{
+       nfs_mark_delegation_revoked(delegation);
+       __nfs_free_delegation(delegation);
+}
+
 /**
  * nfs_mark_delegation_referenced - set delegation's REFERENCED flag
  * @delegation: delegation to process
@@ -343,7 +359,8 @@ nfs_update_inplace_delegation(struct nfs_delegation *delegation,
                delegation->stateid.seqid = update->stateid.seqid;
                smp_wmb();
                delegation->type = update->type;
-               clear_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
+               if (test_and_clear_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
+                       atomic_long_inc(&nfs_active_delegations);
        }
 }
 
@@ -423,6 +440,8 @@ add_new:
        rcu_assign_pointer(nfsi->delegation, delegation);
        delegation = NULL;
 
+       atomic_long_inc(&nfs_active_delegations);
+
        trace_nfs4_set_delegation(inode, type);
 
        spin_lock(&inode->i_lock);
@@ -432,7 +451,7 @@ add_new:
 out:
        spin_unlock(&clp->cl_lock);
        if (delegation != NULL)
-               nfs_free_delegation(delegation);
+               __nfs_free_delegation(delegation);
        if (freeme != NULL) {
                nfs_do_return_delegation(inode, freeme, 0);
                nfs_free_delegation(freeme);
@@ -796,13 +815,6 @@ static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *cl
        rcu_read_unlock();
 }
 
-static void nfs_mark_delegation_revoked(struct nfs_server *server,
-               struct nfs_delegation *delegation)
-{
-       set_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
-       delegation->stateid.type = NFS4_INVALID_STATEID_TYPE;
-}
-
 static void nfs_revoke_delegation(struct inode *inode,
                const nfs4_stateid *stateid)
 {
@@ -830,7 +842,7 @@ static void nfs_revoke_delegation(struct inode *inode,
                }
                spin_unlock(&delegation->lock);
        }
-       nfs_mark_delegation_revoked(NFS_SERVER(inode), delegation);
+       nfs_mark_delegation_revoked(delegation);
        ret = true;
 out:
        rcu_read_unlock();
@@ -869,7 +881,7 @@ void nfs_delegation_mark_returned(struct inode *inode,
                        delegation->stateid.seqid = stateid->seqid;
        }
 
-       nfs_mark_delegation_revoked(NFS_SERVER(inode), delegation);
+       nfs_mark_delegation_revoked(delegation);
 
 out_clear_returning:
        clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags);