nfsd4: use reference count to free client
authorJ. Bruce Fields <bfields@redhat.com>
Thu, 21 Mar 2019 00:03:02 +0000 (20:03 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Wed, 3 Jul 2019 21:52:49 +0000 (17:52 -0400)
Keep a second reference count which is what is really used to decide
when to free the client's memory.

Next I'm going to add an nfsd/clients/ directory with a subdirectory for
each NFSv4 client.  File objects under nfsd/clients/ will hold these
references.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs4state.c
fs/nfsd/state.h

index 194da1700cc44191fd90e1a889a4333832e6f1c5..de68c3cbea2b8f89a05bc56a1dd90ac317244f71 100644 (file)
@@ -1879,6 +1879,24 @@ err_no_name:
        return NULL;
 }
 
+static void __free_client(struct kref *k)
+{
+       struct nfs4_client *clp = container_of(k, struct nfs4_client, cl_ref);
+
+       free_svc_cred(&clp->cl_cred);
+       kfree(clp->cl_ownerstr_hashtbl);
+       kfree(clp->cl_name.data);
+       idr_destroy(&clp->cl_stateids);
+       if (clp->cl_nfsd_dentry)
+               nfsd_client_rmdir(clp->cl_nfsd_dentry);
+       kmem_cache_free(client_slab, clp);
+}
+
+void drop_client(struct nfs4_client *clp)
+{
+       kref_put(&clp->cl_ref, __free_client);
+}
+
 static void
 free_client(struct nfs4_client *clp)
 {
@@ -1891,11 +1909,7 @@ free_client(struct nfs4_client *clp)
                free_session(ses);
        }
        rpc_destroy_wait_queue(&clp->cl_cb_waitq);
-       free_svc_cred(&clp->cl_cred);
-       kfree(clp->cl_ownerstr_hashtbl);
-       kfree(clp->cl_name.data);
-       idr_destroy(&clp->cl_stateids);
-       kmem_cache_free(client_slab, clp);
+       drop_client(clp);
 }
 
 /* must be called under the client_lock */
@@ -2216,6 +2230,8 @@ static struct nfs4_client *create_client(struct xdr_netobj name,
                free_client(clp);
                return NULL;
        }
+
+       kref_init(&clp->cl_ref);
        nfsd4_init_cb(&clp->cl_cb_null, clp, NULL, NFSPROC4_CLNT_CB_NULL);
        clp->cl_time = get_seconds();
        clear_bit(0, &clp->cl_cb_slot_busy);
index f79ad7202e8250fac463567a87d7a49feed9c7bc..8eacdbc50cd7f488a60ffa59e669a4f6d6f1d0ac 100644 (file)
@@ -348,6 +348,7 @@ struct nfs4_client {
        u32                     cl_exchange_flags;
        /* number of rpc's in progress over an associated session: */
        atomic_t                cl_rpc_users;
+       struct kref             cl_ref;
        struct nfs4_op_map      cl_spo_must_allow;
 
        /* for nfs41 callbacks */