aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/callback.c65
-rw-r--r--fs/nfs/callback.h2
-rw-r--r--fs/nfs/client.c21
3 files changed, 54 insertions, 34 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index a886e692ddd0..4b1313eda6f5 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -59,7 +59,7 @@ module_param_call(callback_tcpport, param_set_port, param_get_int,
59 * This is the callback kernel thread. 59 * This is the callback kernel thread.
60 */ 60 */
61static int 61static int
62nfs_callback_svc(void *vrqstp) 62nfs4_callback_svc(void *vrqstp)
63{ 63{
64 int err, preverr = 0; 64 int err, preverr = 0;
65 struct svc_rqst *rqstp = vrqstp; 65 struct svc_rqst *rqstp = vrqstp;
@@ -97,20 +97,12 @@ nfs_callback_svc(void *vrqstp)
97} 97}
98 98
99/* 99/*
100 * Bring up the callback thread if it is not already up. 100 * Prepare to bring up the NFSv4 callback service
101 */ 101 */
102int nfs_callback_up(void) 102struct svc_rqst *
103nfs4_callback_up(struct svc_serv *serv)
103{ 104{
104 struct svc_serv *serv = NULL; 105 int ret;
105 int ret = 0;
106
107 mutex_lock(&nfs_callback_mutex);
108 if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
109 goto out;
110 serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
111 ret = -ENOMEM;
112 if (!serv)
113 goto out_err;
114 106
115 ret = svc_create_xprt(serv, "tcp", PF_INET, 107 ret = svc_create_xprt(serv, "tcp", PF_INET,
116 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); 108 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
@@ -131,18 +123,53 @@ int nfs_callback_up(void)
131 goto out_err; 123 goto out_err;
132#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ 124#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
133 125
134 nfs_callback_info.rqst = svc_prepare_thread(serv, &serv->sv_pools[0]); 126 return svc_prepare_thread(serv, &serv->sv_pools[0]);
135 if (IS_ERR(nfs_callback_info.rqst)) { 127
136 ret = PTR_ERR(nfs_callback_info.rqst); 128out_err:
137 nfs_callback_info.rqst = NULL; 129 if (ret == 0)
130 ret = -ENOMEM;
131 return ERR_PTR(ret);
132}
133
134/*
135 * Bring up the callback thread if it is not already up.
136 */
137int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
138{
139 struct svc_serv *serv = NULL;
140 struct svc_rqst *rqstp;
141 int (*callback_svc)(void *vrqstp);
142 char svc_name[12];
143 int ret = 0;
144
145 mutex_lock(&nfs_callback_mutex);
146 if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
147 goto out;
148 serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
149 if (!serv) {
150 ret = -ENOMEM;
151 goto out_err;
152 }
153
154 if (!minorversion) {
155 rqstp = nfs4_callback_up(serv);
156 callback_svc = nfs4_callback_svc;
157 } else {
158 BUG(); /* for now */
159 }
160
161 if (IS_ERR(rqstp)) {
162 ret = PTR_ERR(rqstp);
138 goto out_err; 163 goto out_err;
139 } 164 }
140 165
141 svc_sock_update_bufs(serv); 166 svc_sock_update_bufs(serv);
142 167
143 nfs_callback_info.task = kthread_run(nfs_callback_svc, 168 sprintf(svc_name, "nfsv4.%u-svc", minorversion);
169 nfs_callback_info.rqst = rqstp;
170 nfs_callback_info.task = kthread_run(callback_svc,
144 nfs_callback_info.rqst, 171 nfs_callback_info.rqst,
145 "nfsv4-svc"); 172 svc_name);
146 if (IS_ERR(nfs_callback_info.task)) { 173 if (IS_ERR(nfs_callback_info.task)) {
147 ret = PTR_ERR(nfs_callback_info.task); 174 ret = PTR_ERR(nfs_callback_info.task);
148 svc_exit_thread(nfs_callback_info.rqst); 175 svc_exit_thread(nfs_callback_info.rqst);
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index e110e286a262..9b907f408b8d 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -63,7 +63,7 @@ extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getat
63extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy); 63extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
64 64
65#ifdef CONFIG_NFS_V4 65#ifdef CONFIG_NFS_V4
66extern int nfs_callback_up(void); 66extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt);
67extern void nfs_callback_down(void); 67extern void nfs_callback_down(void);
68#else 68#else
69#define nfs_callback_up() (0) 69#define nfs_callback_up() (0)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index d9657d455730..df2b40d1883d 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -47,9 +47,6 @@
47#include "internal.h" 47#include "internal.h"
48#include "fscache.h" 48#include "fscache.h"
49 49
50static int nfs4_init_callback(struct nfs_client *);
51static void nfs4_destroy_callback(struct nfs_client *);
52
53#define NFSDBG_FACILITY NFSDBG_CLIENT 50#define NFSDBG_FACILITY NFSDBG_CLIENT
54 51
55static DEFINE_SPINLOCK(nfs_client_lock); 52static DEFINE_SPINLOCK(nfs_client_lock);
@@ -124,9 +121,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
124 121
125 clp->rpc_ops = cl_init->rpc_ops; 122 clp->rpc_ops = cl_init->rpc_ops;
126 123
127 if (nfs4_init_callback(clp) < 0)
128 goto error_2;
129
130 atomic_set(&clp->cl_count, 1); 124 atomic_set(&clp->cl_count, 1);
131 clp->cl_cons_state = NFS_CS_INITING; 125 clp->cl_cons_state = NFS_CS_INITING;
132 126
@@ -136,7 +130,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
136 if (cl_init->hostname) { 130 if (cl_init->hostname) {
137 clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL); 131 clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL);
138 if (!clp->cl_hostname) 132 if (!clp->cl_hostname)
139 goto error_3; 133 goto error_cleanup;
140 } 134 }
141 135
142 INIT_LIST_HEAD(&clp->cl_superblocks); 136 INIT_LIST_HEAD(&clp->cl_superblocks);
@@ -161,9 +155,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
161 155
162 return clp; 156 return clp;
163 157
164error_3: 158error_cleanup:
165 nfs4_destroy_callback(clp);
166error_2:
167 kfree(clp); 159 kfree(clp);
168error_0: 160error_0:
169 return NULL; 161 return NULL;
@@ -207,6 +199,8 @@ static void nfs4_clear_client_minor_version(struct nfs_client *clp)
207 199
208 clp->cl_call_sync = _nfs4_call_sync; 200 clp->cl_call_sync = _nfs4_call_sync;
209#endif /* CONFIG_NFS_V4_1 */ 201#endif /* CONFIG_NFS_V4_1 */
202
203 nfs4_destroy_callback(clp);
210} 204}
211 205
212/* 206/*
@@ -225,8 +219,6 @@ static void nfs_free_client(struct nfs_client *clp)
225 if (!IS_ERR(clp->cl_rpcclient)) 219 if (!IS_ERR(clp->cl_rpcclient))
226 rpc_shutdown_client(clp->cl_rpcclient); 220 rpc_shutdown_client(clp->cl_rpcclient);
227 221
228 nfs4_destroy_callback(clp);
229
230 if (clp->cl_machine_cred != NULL) 222 if (clp->cl_machine_cred != NULL)
231 put_rpccred(clp->cl_machine_cred); 223 put_rpccred(clp->cl_machine_cred);
232 224
@@ -1104,7 +1096,8 @@ static int nfs4_init_callback(struct nfs_client *clp)
1104 int error; 1096 int error;
1105 1097
1106 if (clp->rpc_ops->version == 4) { 1098 if (clp->rpc_ops->version == 4) {
1107 error = nfs_callback_up(); 1099 error = nfs_callback_up(clp->cl_minorversion,
1100 clp->cl_rpcclient->cl_xprt);
1108 if (error < 0) { 1101 if (error < 0) {
1109 dprintk("%s: failed to start callback. Error = %d\n", 1102 dprintk("%s: failed to start callback. Error = %d\n",
1110 __func__, error); 1103 __func__, error);
@@ -1139,7 +1132,7 @@ static int nfs4_init_client_minor_version(struct nfs_client *clp)
1139 } 1132 }
1140#endif /* CONFIG_NFS_V4_1 */ 1133#endif /* CONFIG_NFS_V4_1 */
1141 1134
1142 return 0; 1135 return nfs4_init_callback(clp);
1143} 1136}
1144 1137
1145/* 1138/*