- if (server->mnt_path) {
- kfree(server->mnt_path);
- server->mnt_path = NULL;
- }
- if (server->nfs4_state) {
- nfs4_put_client(server->nfs4_state);
- server->nfs4_state = NULL;
- }
-}
-
-/*
- * nfs4_get_client(): returns an empty client structure
- * nfs4_put_client(): drops reference to client structure
- *
- * Since these are allocated/deallocated very rarely, we don't
- * bother putting them in a slab cache...
- */
-static struct nfs4_client *
-nfs4_alloc_client(struct in_addr *addr)
-{
- struct nfs4_client *clp;
-
- if ((clp = kmalloc(sizeof(*clp), GFP_KERNEL))) {
- memset(clp, 0, sizeof(*clp));
- memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
- init_rwsem(&clp->cl_sem);
- INIT_LIST_HEAD(&clp->cl_state_owners);
- INIT_LIST_HEAD(&clp->cl_unused);
- spin_lock_init(&clp->cl_lock);
- atomic_set(&clp->cl_count, 1);
- INIT_WORK(&clp->cl_recoverd, nfs4_recover_state, clp);
- INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
- INIT_LIST_HEAD(&clp->cl_superblocks);
- init_waitqueue_head(&clp->cl_waitq);
- rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
- clp->cl_state = 1 << NFS4CLNT_NEW;
- }
- return clp;
-}
-
-static void
-nfs4_free_client(struct nfs4_client *clp)
-{
- struct nfs4_state_owner *sp;
-
- while (!list_empty(&clp->cl_unused)) {
- sp = list_entry(clp->cl_unused.next,
- struct nfs4_state_owner,
- so_list);
- list_del(&sp->so_list);
- kfree(sp);
- }
- BUG_ON(!list_empty(&clp->cl_state_owners));
- if (clp->cl_cred)
- put_rpccred(clp->cl_cred);
- nfs_idmap_delete(clp);
- if (clp->cl_rpcclient)
- rpc_shutdown_client(clp->cl_rpcclient);
- kfree(clp);
-}
-
-struct nfs4_client *
-nfs4_get_client(struct in_addr *addr)
-{
- struct nfs4_client *new, *clp = NULL;
-
- new = nfs4_alloc_client(addr);
- spin_lock(&state_spinlock);
- list_for_each_entry(clp, &nfs4_clientid_list, cl_servers) {
- if (memcmp(&clp->cl_addr, addr, sizeof(clp->cl_addr)) == 0)
- goto found;
- }
- if (new)
- list_add(&new->cl_servers, &nfs4_clientid_list);
- spin_unlock(&state_spinlock);
- return new;
-found:
- atomic_inc(&clp->cl_count);
- spin_unlock(&state_spinlock);
- if (new)
- nfs4_free_client(new);
- return clp;
-}
-
-void
-nfs4_put_client(struct nfs4_client *clp)
-{
- if (!atomic_dec_and_lock(&clp->cl_count, &state_spinlock))
- return;
- list_del(&clp->cl_servers);
- spin_unlock(&state_spinlock);
- BUG_ON(!list_empty(&clp->cl_superblocks));
- wake_up_all(&clp->cl_waitq);
- rpc_wake_up(&clp->cl_rpcwaitq);
- nfs4_kill_renewd(clp);
- nfs4_free_client(clp);