aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4client.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4client.c')
-rw-r--r--fs/nfs/nfs4client.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index a71d95ecbea9..1c3f13c8e472 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -23,6 +23,97 @@
23static bool nfs4_disable_idmapping = true; 23static bool nfs4_disable_idmapping = true;
24 24
25/* 25/*
26 * Get a unique NFSv4.0 callback identifier which will be used
27 * by the V4.0 callback service to lookup the nfs_client struct
28 */
29static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
30{
31 int ret = 0;
32 struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
33
34 if (clp->rpc_ops->version != 4 || minorversion != 0)
35 return ret;
36retry:
37 if (!idr_pre_get(&nn->cb_ident_idr, GFP_KERNEL))
38 return -ENOMEM;
39 spin_lock(&nn->nfs_client_lock);
40 ret = idr_get_new(&nn->cb_ident_idr, clp, &clp->cl_cb_ident);
41 spin_unlock(&nn->nfs_client_lock);
42 if (ret == -EAGAIN)
43 goto retry;
44 return ret;
45}
46
47#ifdef CONFIG_NFS_V4_1
48static void nfs4_shutdown_session(struct nfs_client *clp)
49{
50 if (nfs4_has_session(clp)) {
51 nfs4_destroy_session(clp->cl_session);
52 nfs4_destroy_clientid(clp);
53 }
54
55}
56#else /* CONFIG_NFS_V4_1 */
57static void nfs4_shutdown_session(struct nfs_client *clp)
58{
59}
60#endif /* CONFIG_NFS_V4_1 */
61
62struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
63{
64 int err;
65 struct nfs_client *clp = nfs_alloc_client(cl_init);
66 if (IS_ERR(clp))
67 return clp;
68
69 err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
70 if (err)
71 goto error;
72
73 spin_lock_init(&clp->cl_lock);
74 INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
75 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
76 clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
77 clp->cl_minorversion = cl_init->minorversion;
78 clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
79 return clp;
80
81error:
82 kfree(clp);
83 return ERR_PTR(err);
84}
85
86/*
87 * Destroy the NFS4 callback service
88 */
89static void nfs4_destroy_callback(struct nfs_client *clp)
90{
91 if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
92 nfs_callback_down(clp->cl_mvops->minor_version);
93}
94
95static void nfs4_shutdown_client(struct nfs_client *clp)
96{
97 if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
98 nfs4_kill_renewd(clp);
99 nfs4_shutdown_session(clp);
100 nfs4_destroy_callback(clp);
101 if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
102 nfs_idmap_delete(clp);
103
104 rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
105 kfree(clp->cl_serverowner);
106 kfree(clp->cl_serverscope);
107 kfree(clp->cl_implid);
108}
109
110void nfs4_free_client(struct nfs_client *clp)
111{
112 nfs4_shutdown_client(clp);
113 nfs_free_client(clp);
114}
115
116/*
26 * Initialize the NFS4 callback service 117 * Initialize the NFS4 callback service
27 */ 118 */
28static int nfs4_init_callback(struct nfs_client *clp) 119static int nfs4_init_callback(struct nfs_client *clp)