diff options
author | Andy Adamson <andros@netapp.com> | 2009-04-01 09:23:14 -0400 |
---|---|---|
committer | Benny Halevy <bhalevy@panasas.com> | 2009-06-17 17:11:32 -0400 |
commit | e82dc22dac6525a2f365a1d53c0483252d4aa38e (patch) | |
tree | 1a347b34c955db77017a5df533fc1798f164e768 | |
parent | 8f975242352e92898dc641ebff0d24808f39848a (diff) |
nfs41: Allow NFSv4 and NFSv4.1 callback services to coexist
Tracks the nfs_callback_info for both versions, enabling the callback
service for v4 and v4.1 to run concurrently and be stopped independently
of each other.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
-rw-r--r-- | fs/nfs/callback.c | 50 | ||||
-rw-r--r-- | fs/nfs/callback.h | 7 | ||||
-rw-r--r-- | fs/nfs/client.c | 2 |
3 files changed, 27 insertions, 32 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 37815f3216aa..e69b8f61189e 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -36,7 +36,7 @@ struct nfs_callback_data { | |||
36 | struct task_struct *task; | 36 | struct task_struct *task; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | static struct nfs_callback_data nfs_callback_info; | 39 | static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1]; |
40 | static DEFINE_MUTEX(nfs_callback_mutex); | 40 | static DEFINE_MUTEX(nfs_callback_mutex); |
41 | static struct svc_program nfs4_callback_program; | 41 | static struct svc_program nfs4_callback_program; |
42 | 42 | ||
@@ -60,7 +60,7 @@ module_param_call(callback_tcpport, param_set_port, param_get_int, | |||
60 | &nfs_callback_set_tcpport, 0644); | 60 | &nfs_callback_set_tcpport, 0644); |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * This is the callback kernel thread. | 63 | * This is the NFSv4 callback kernel thread. |
64 | */ | 64 | */ |
65 | static int | 65 | static int |
66 | nfs4_callback_svc(void *vrqstp) | 66 | nfs4_callback_svc(void *vrqstp) |
@@ -174,8 +174,6 @@ nfs41_callback_svc(void *vrqstp) | |||
174 | finish_wait(&serv->sv_cb_waitq, &wq); | 174 | finish_wait(&serv->sv_cb_waitq, &wq); |
175 | } | 175 | } |
176 | unlock_kernel(); | 176 | unlock_kernel(); |
177 | nfs_callback_info.task = NULL; | ||
178 | svc_exit_thread(rqstp); | ||
179 | return 0; | 177 | return 0; |
180 | } | 178 | } |
181 | 179 | ||
@@ -251,13 +249,14 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) | |||
251 | struct svc_serv *serv = NULL; | 249 | struct svc_serv *serv = NULL; |
252 | struct svc_rqst *rqstp; | 250 | struct svc_rqst *rqstp; |
253 | int (*callback_svc)(void *vrqstp); | 251 | int (*callback_svc)(void *vrqstp); |
252 | struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; | ||
254 | char svc_name[12]; | 253 | char svc_name[12]; |
255 | int ret = 0; | 254 | int ret = 0; |
256 | int minorversion_setup; | 255 | int minorversion_setup; |
257 | 256 | ||
258 | mutex_lock(&nfs_callback_mutex); | 257 | mutex_lock(&nfs_callback_mutex); |
259 | if (nfs_callback_info.users++ || nfs_callback_info.task != NULL) { | 258 | if (cb_info->users++ || cb_info->task != NULL) { |
260 | nfs_callback_bc_serv(minorversion, xprt, &nfs_callback_info); | 259 | nfs_callback_bc_serv(minorversion, xprt, cb_info); |
261 | goto out; | 260 | goto out; |
262 | } | 261 | } |
263 | serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL); | 262 | serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL); |
@@ -282,17 +281,14 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) | |||
282 | svc_sock_update_bufs(serv); | 281 | svc_sock_update_bufs(serv); |
283 | 282 | ||
284 | sprintf(svc_name, "nfsv4.%u-svc", minorversion); | 283 | sprintf(svc_name, "nfsv4.%u-svc", minorversion); |
285 | nfs_callback_info.serv = serv; | 284 | cb_info->serv = serv; |
286 | nfs_callback_info.rqst = rqstp; | 285 | cb_info->rqst = rqstp; |
287 | nfs_callback_info.task = kthread_run(callback_svc, | 286 | cb_info->task = kthread_run(callback_svc, cb_info->rqst, svc_name); |
288 | nfs_callback_info.rqst, | 287 | if (IS_ERR(cb_info->task)) { |
289 | svc_name); | 288 | ret = PTR_ERR(cb_info->task); |
290 | if (IS_ERR(nfs_callback_info.task)) { | 289 | svc_exit_thread(cb_info->rqst); |
291 | ret = PTR_ERR(nfs_callback_info.task); | 290 | cb_info->rqst = NULL; |
292 | svc_exit_thread(nfs_callback_info.rqst); | 291 | cb_info->task = NULL; |
293 | nfs_callback_info.serv = NULL; | ||
294 | nfs_callback_info.rqst = NULL; | ||
295 | nfs_callback_info.task = NULL; | ||
296 | goto out_err; | 292 | goto out_err; |
297 | } | 293 | } |
298 | out: | 294 | out: |
@@ -309,23 +305,25 @@ out: | |||
309 | out_err: | 305 | out_err: |
310 | dprintk("NFS: Couldn't create callback socket or server thread; " | 306 | dprintk("NFS: Couldn't create callback socket or server thread; " |
311 | "err = %d\n", ret); | 307 | "err = %d\n", ret); |
312 | nfs_callback_info.users--; | 308 | cb_info->users--; |
313 | goto out; | 309 | goto out; |
314 | } | 310 | } |
315 | 311 | ||
316 | /* | 312 | /* |
317 | * Kill the callback thread if it's no longer being used. | 313 | * Kill the callback thread if it's no longer being used. |
318 | */ | 314 | */ |
319 | void nfs_callback_down(void) | 315 | void nfs_callback_down(int minorversion) |
320 | { | 316 | { |
317 | struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; | ||
318 | |||
321 | mutex_lock(&nfs_callback_mutex); | 319 | mutex_lock(&nfs_callback_mutex); |
322 | nfs_callback_info.users--; | 320 | cb_info->users--; |
323 | if (nfs_callback_info.users == 0 && nfs_callback_info.task != NULL) { | 321 | if (cb_info->users == 0 && cb_info->task != NULL) { |
324 | kthread_stop(nfs_callback_info.task); | 322 | kthread_stop(cb_info->task); |
325 | svc_exit_thread(nfs_callback_info.rqst); | 323 | svc_exit_thread(cb_info->rqst); |
326 | nfs_callback_info.serv = NULL; | 324 | cb_info->serv = NULL; |
327 | nfs_callback_info.rqst = NULL; | 325 | cb_info->rqst = NULL; |
328 | nfs_callback_info.task = NULL; | 326 | cb_info->task = NULL; |
329 | } | 327 | } |
330 | mutex_unlock(&nfs_callback_mutex); | 328 | mutex_unlock(&nfs_callback_mutex); |
331 | } | 329 | } |
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index 29123b5604f2..88d2e1135b5a 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h | |||
@@ -64,11 +64,8 @@ extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy); | |||
64 | 64 | ||
65 | #ifdef CONFIG_NFS_V4 | 65 | #ifdef CONFIG_NFS_V4 |
66 | extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt); | 66 | extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt); |
67 | extern void nfs_callback_down(void); | 67 | extern void nfs_callback_down(int minorversion); |
68 | #else | 68 | #endif /* CONFIG_NFS_V4 */ |
69 | #define nfs_callback_up() (0) | ||
70 | #define nfs_callback_down() do {} while(0) | ||
71 | #endif | ||
72 | 69 | ||
73 | /* | 70 | /* |
74 | * nfs41: Callbacks are expected to not cause substantial latency, | 71 | * nfs41: Callbacks are expected to not cause substantial latency, |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index df2b40d1883d..ac6575c4da31 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -181,7 +181,7 @@ static void nfs4_destroy_callback(struct nfs_client *clp) | |||
181 | { | 181 | { |
182 | #ifdef CONFIG_NFS_V4 | 182 | #ifdef CONFIG_NFS_V4 |
183 | if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) | 183 | if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) |
184 | nfs_callback_down(); | 184 | nfs_callback_down(clp->cl_minorversion); |
185 | #endif /* CONFIG_NFS_V4 */ | 185 | #endif /* CONFIG_NFS_V4 */ |
186 | } | 186 | } |
187 | 187 | ||