diff options
author | NeilBrown <neilb@suse.de> | 2006-10-02 05:17:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 10:57:17 -0400 |
commit | 24e36663c375df577d2dcae437713481ffd6850c (patch) | |
tree | dd738e582b663c433eef3a53eb593a518439a285 | |
parent | bc591ccff27e6a85d3a0d6fcb16cfadcc45267a8 (diff) |
[PATCH] knfsd: be more selective in which sockets lockd listens on
Currently lockd listens on UDP always, and TCP if CONFIG_NFSD_TCP is set.
However as lockd performs services of the client as well, this is a problem.
If CONFIG_NfSD_TCP is not set, and a tcp mount is used, the server will not be
able to call back to lockd.
So:
- add an option to lockd_up saying which protocol is needed
- Always open sockets for which an explicit port was given, otherwise
only open a socket of the type required
- Change nfsd to do one lockd_up per socket rather than one per thread.
This
- removes the dependancy on CONFIG_NFSD_TCP
- means that lockd may open sockets other than at startup
- means that lockd will *not* listen on UDP if the only
mounts are TCP mount (and nfsd hasn't started).
The latter is the only one that concerns me at all - I don't know if this
might be a problem with some servers.
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/lockd/clntlock.c | 2 | ||||
-rw-r--r-- | fs/lockd/svc.c | 47 | ||||
-rw-r--r-- | fs/nfs/client.c | 3 | ||||
-rw-r--r-- | fs/nfsd/nfssvc.c | 16 | ||||
-rw-r--r-- | include/linux/lockd/bind.h | 2 |
5 files changed, 54 insertions, 16 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index f95cc3f3c42d..6abb465b650f 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c | |||
@@ -202,7 +202,7 @@ reclaimer(void *ptr) | |||
202 | /* This one ensures that our parent doesn't terminate while the | 202 | /* This one ensures that our parent doesn't terminate while the |
203 | * reclaim is in progress */ | 203 | * reclaim is in progress */ |
204 | lock_kernel(); | 204 | lock_kernel(); |
205 | lockd_up(); | 205 | lockd_up(0); |
206 | 206 | ||
207 | nlmclnt_prepare_reclaim(host); | 207 | nlmclnt_prepare_reclaim(host); |
208 | /* First, reclaim all locks that have been marked. */ | 208 | /* First, reclaim all locks that have been marked. */ |
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 13feba45030e..8d19de6a14dc 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/sunrpc/clnt.h> | 31 | #include <linux/sunrpc/clnt.h> |
32 | #include <linux/sunrpc/svc.h> | 32 | #include <linux/sunrpc/svc.h> |
33 | #include <linux/sunrpc/svcsock.h> | 33 | #include <linux/sunrpc/svcsock.h> |
34 | #include <net/ip.h> | ||
34 | #include <linux/lockd/lockd.h> | 35 | #include <linux/lockd/lockd.h> |
35 | #include <linux/nfs.h> | 36 | #include <linux/nfs.h> |
36 | 37 | ||
@@ -46,6 +47,7 @@ EXPORT_SYMBOL(nlmsvc_ops); | |||
46 | static DEFINE_MUTEX(nlmsvc_mutex); | 47 | static DEFINE_MUTEX(nlmsvc_mutex); |
47 | static unsigned int nlmsvc_users; | 48 | static unsigned int nlmsvc_users; |
48 | static pid_t nlmsvc_pid; | 49 | static pid_t nlmsvc_pid; |
50 | static struct svc_serv *nlmsvc_serv; | ||
49 | int nlmsvc_grace_period; | 51 | int nlmsvc_grace_period; |
50 | unsigned long nlmsvc_timeout; | 52 | unsigned long nlmsvc_timeout; |
51 | 53 | ||
@@ -112,6 +114,7 @@ lockd(struct svc_rqst *rqstp) | |||
112 | * Let our maker know we're running. | 114 | * Let our maker know we're running. |
113 | */ | 115 | */ |
114 | nlmsvc_pid = current->pid; | 116 | nlmsvc_pid = current->pid; |
117 | nlmsvc_serv = serv; | ||
115 | complete(&lockd_start_done); | 118 | complete(&lockd_start_done); |
116 | 119 | ||
117 | daemonize("lockd"); | 120 | daemonize("lockd"); |
@@ -189,6 +192,7 @@ lockd(struct svc_rqst *rqstp) | |||
189 | nlmsvc_invalidate_all(); | 192 | nlmsvc_invalidate_all(); |
190 | nlm_shutdown_hosts(); | 193 | nlm_shutdown_hosts(); |
191 | nlmsvc_pid = 0; | 194 | nlmsvc_pid = 0; |
195 | nlmsvc_serv = NULL; | ||
192 | } else | 196 | } else |
193 | printk(KERN_DEBUG | 197 | printk(KERN_DEBUG |
194 | "lockd: new process, skipping host shutdown\n"); | 198 | "lockd: new process, skipping host shutdown\n"); |
@@ -205,11 +209,42 @@ lockd(struct svc_rqst *rqstp) | |||
205 | module_put_and_exit(0); | 209 | module_put_and_exit(0); |
206 | } | 210 | } |
207 | 211 | ||
212 | |||
213 | static int find_socket(struct svc_serv *serv, int proto) | ||
214 | { | ||
215 | struct svc_sock *svsk; | ||
216 | int found = 0; | ||
217 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) | ||
218 | if (svsk->sk_sk->sk_protocol == proto) { | ||
219 | found = 1; | ||
220 | break; | ||
221 | } | ||
222 | return found; | ||
223 | } | ||
224 | |||
225 | static int make_socks(struct svc_serv *serv, int proto) | ||
226 | { | ||
227 | /* Make any sockets that are needed but not present. | ||
228 | * If nlm_udpport or nlm_tcpport were set as module | ||
229 | * options, make those sockets unconditionally | ||
230 | */ | ||
231 | int err = 0; | ||
232 | if (proto == IPPROTO_UDP || nlm_udpport) | ||
233 | if (!find_socket(serv, IPPROTO_UDP)) | ||
234 | err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport); | ||
235 | if (err) | ||
236 | return err; | ||
237 | if (proto == IPPROTO_TCP || nlm_tcpport) | ||
238 | if (!find_socket(serv, IPPROTO_TCP)) | ||
239 | err= svc_makesock(serv, IPPROTO_TCP, nlm_tcpport); | ||
240 | return err; | ||
241 | } | ||
242 | |||
208 | /* | 243 | /* |
209 | * Bring up the lockd process if it's not already up. | 244 | * Bring up the lockd process if it's not already up. |
210 | */ | 245 | */ |
211 | int | 246 | int |
212 | lockd_up(void) | 247 | lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */ |
213 | { | 248 | { |
214 | static int warned; | 249 | static int warned; |
215 | struct svc_serv * serv; | 250 | struct svc_serv * serv; |
@@ -224,8 +259,10 @@ lockd_up(void) | |||
224 | /* | 259 | /* |
225 | * Check whether we're already up and running. | 260 | * Check whether we're already up and running. |
226 | */ | 261 | */ |
227 | if (nlmsvc_pid) | 262 | if (nlmsvc_pid) { |
263 | error = make_socks(nlmsvc_serv, proto); | ||
228 | goto out; | 264 | goto out; |
265 | } | ||
229 | 266 | ||
230 | /* | 267 | /* |
231 | * Sanity check: if there's no pid, | 268 | * Sanity check: if there's no pid, |
@@ -242,11 +279,7 @@ lockd_up(void) | |||
242 | goto out; | 279 | goto out; |
243 | } | 280 | } |
244 | 281 | ||
245 | if ((error = svc_makesock(serv, IPPROTO_UDP, nlm_udpport)) < 0 | 282 | if ((error = make_socks(serv, proto)) < 0) { |
246 | #ifdef CONFIG_NFSD_TCP | ||
247 | || (error = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport)) < 0 | ||
248 | #endif | ||
249 | ) { | ||
250 | if (warned++ == 0) | 283 | if (warned++ == 0) |
251 | printk(KERN_WARNING | 284 | printk(KERN_WARNING |
252 | "lockd_up: makesock failed, error=%d\n", error); | 285 | "lockd_up: makesock failed, error=%d\n", error); |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index ec1938d4b814..8106f3b29e4a 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -460,7 +460,8 @@ static int nfs_start_lockd(struct nfs_server *server) | |||
460 | goto out; | 460 | goto out; |
461 | if (server->flags & NFS_MOUNT_NONLM) | 461 | if (server->flags & NFS_MOUNT_NONLM) |
462 | goto out; | 462 | goto out; |
463 | error = lockd_up(); | 463 | error = lockd_up((server->flags & NFS_MOUNT_TCP) ? |
464 | IPPROTO_TCP : IPPROTO_UDP); | ||
464 | if (error < 0) | 465 | if (error < 0) |
465 | server->flags |= NFS_MOUNT_NONLM; | 466 | server->flags |= NFS_MOUNT_NONLM; |
466 | else | 467 | else |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index c52c99964a4c..0339b4ddfa3b 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
@@ -134,6 +134,9 @@ static int killsig; /* signal that was used to kill last nfsd */ | |||
134 | static void nfsd_last_thread(struct svc_serv *serv) | 134 | static void nfsd_last_thread(struct svc_serv *serv) |
135 | { | 135 | { |
136 | /* When last nfsd thread exits we need to do some clean-up */ | 136 | /* When last nfsd thread exits we need to do some clean-up */ |
137 | struct svc_sock *svsk; | ||
138 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) | ||
139 | lockd_down(); | ||
137 | nfsd_serv = NULL; | 140 | nfsd_serv = NULL; |
138 | nfsd_racache_shutdown(); | 141 | nfsd_racache_shutdown(); |
139 | nfs4_state_shutdown(); | 142 | nfs4_state_shutdown(); |
@@ -218,11 +221,16 @@ nfsd_svc(unsigned short port, int nrservs) | |||
218 | error = svc_makesock(nfsd_serv, IPPROTO_UDP, port); | 221 | error = svc_makesock(nfsd_serv, IPPROTO_UDP, port); |
219 | if (error < 0) | 222 | if (error < 0) |
220 | goto failure; | 223 | goto failure; |
221 | 224 | error = lockd_up(IPPROTO_UDP); | |
225 | if (error < 0) | ||
226 | goto failure; | ||
222 | #ifdef CONFIG_NFSD_TCP | 227 | #ifdef CONFIG_NFSD_TCP |
223 | error = svc_makesock(nfsd_serv, IPPROTO_TCP, port); | 228 | error = svc_makesock(nfsd_serv, IPPROTO_TCP, port); |
224 | if (error < 0) | 229 | if (error < 0) |
225 | goto failure; | 230 | goto failure; |
231 | error = lockd_up(IPPROTO_TCP); | ||
232 | if (error < 0) | ||
233 | goto failure; | ||
226 | #endif | 234 | #endif |
227 | do_gettimeofday(&nfssvc_boot); /* record boot time */ | 235 | do_gettimeofday(&nfssvc_boot); /* record boot time */ |
228 | } else | 236 | } else |
@@ -306,8 +314,6 @@ nfsd(struct svc_rqst *rqstp) | |||
306 | 314 | ||
307 | nfsdstats.th_cnt++; | 315 | nfsdstats.th_cnt++; |
308 | 316 | ||
309 | lockd_up(); /* start lockd */ | ||
310 | |||
311 | me.task = current; | 317 | me.task = current; |
312 | list_add(&me.list, &nfsd_list); | 318 | list_add(&me.list, &nfsd_list); |
313 | 319 | ||
@@ -364,13 +370,11 @@ nfsd(struct svc_rqst *rqstp) | |||
364 | break; | 370 | break; |
365 | killsig = signo; | 371 | killsig = signo; |
366 | } | 372 | } |
367 | /* Clear signals before calling lockd_down() and svc_exit_thread() */ | 373 | /* Clear signals before calling svc_exit_thread() */ |
368 | flush_signals(current); | 374 | flush_signals(current); |
369 | 375 | ||
370 | lock_kernel(); | 376 | lock_kernel(); |
371 | 377 | ||
372 | /* Release lockd */ | ||
373 | lockd_down(); | ||
374 | list_del(&me.list); | 378 | list_del(&me.list); |
375 | nfsdstats.th_cnt --; | 379 | nfsdstats.th_cnt --; |
376 | 380 | ||
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h index b054debef2e0..81e3a185f951 100644 --- a/include/linux/lockd/bind.h +++ b/include/linux/lockd/bind.h | |||
@@ -30,7 +30,7 @@ extern struct nlmsvc_binding * nlmsvc_ops; | |||
30 | * Functions exported by the lockd module | 30 | * Functions exported by the lockd module |
31 | */ | 31 | */ |
32 | extern int nlmclnt_proc(struct inode *, int, struct file_lock *); | 32 | extern int nlmclnt_proc(struct inode *, int, struct file_lock *); |
33 | extern int lockd_up(void); | 33 | extern int lockd_up(int proto); |
34 | extern void lockd_down(void); | 34 | extern void lockd_down(void); |
35 | 35 | ||
36 | #endif /* LINUX_LOCKD_BIND_H */ | 36 | #endif /* LINUX_LOCKD_BIND_H */ |