diff options
author | Scott Mayhew <smayhew@redhat.com> | 2015-12-11 16:46:00 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2015-12-23 10:08:16 -0500 |
commit | 0751ddf77b6af2efe1041efb81141badd64efb65 (patch) | |
tree | ed777a2c5ff8a510ea28d7262912df8aba59281d | |
parent | 366849966f20a3d996a2160778861e348cc6a7c6 (diff) |
lockd: Register callbacks on the inetaddr_chain and inet6addr_chain
Register callbacks on inetaddr_chain and inet6addr_chain to trigger
cleanup of lockd transport sockets when an ip address is deleted.
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r-- | fs/lockd/svc.c | 74 |
1 files changed, 72 insertions, 2 deletions
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 5f31ebd96c06..44d18ad4d364 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c | |||
@@ -25,13 +25,17 @@ | |||
25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
26 | #include <linux/kthread.h> | 26 | #include <linux/kthread.h> |
27 | #include <linux/freezer.h> | 27 | #include <linux/freezer.h> |
28 | #include <linux/inetdevice.h> | ||
28 | 29 | ||
29 | #include <linux/sunrpc/types.h> | 30 | #include <linux/sunrpc/types.h> |
30 | #include <linux/sunrpc/stats.h> | 31 | #include <linux/sunrpc/stats.h> |
31 | #include <linux/sunrpc/clnt.h> | 32 | #include <linux/sunrpc/clnt.h> |
32 | #include <linux/sunrpc/svc.h> | 33 | #include <linux/sunrpc/svc.h> |
33 | #include <linux/sunrpc/svcsock.h> | 34 | #include <linux/sunrpc/svcsock.h> |
35 | #include <linux/sunrpc/svc_xprt.h> | ||
34 | #include <net/ip.h> | 36 | #include <net/ip.h> |
37 | #include <net/addrconf.h> | ||
38 | #include <net/ipv6.h> | ||
35 | #include <linux/lockd/lockd.h> | 39 | #include <linux/lockd/lockd.h> |
36 | #include <linux/nfs.h> | 40 | #include <linux/nfs.h> |
37 | 41 | ||
@@ -279,6 +283,68 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net) | |||
279 | } | 283 | } |
280 | } | 284 | } |
281 | 285 | ||
286 | static int lockd_inetaddr_event(struct notifier_block *this, | ||
287 | unsigned long event, void *ptr) | ||
288 | { | ||
289 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; | ||
290 | struct sockaddr_in sin; | ||
291 | |||
292 | if (event != NETDEV_DOWN) | ||
293 | goto out; | ||
294 | |||
295 | if (nlmsvc_rqst) { | ||
296 | dprintk("lockd_inetaddr_event: removed %pI4\n", | ||
297 | &ifa->ifa_local); | ||
298 | sin.sin_family = AF_INET; | ||
299 | sin.sin_addr.s_addr = ifa->ifa_local; | ||
300 | svc_age_temp_xprts_now(nlmsvc_rqst->rq_server, | ||
301 | (struct sockaddr *)&sin); | ||
302 | } | ||
303 | |||
304 | out: | ||
305 | return NOTIFY_DONE; | ||
306 | } | ||
307 | |||
308 | static struct notifier_block lockd_inetaddr_notifier = { | ||
309 | .notifier_call = lockd_inetaddr_event, | ||
310 | }; | ||
311 | |||
312 | #if IS_ENABLED(CONFIG_IPV6) | ||
313 | static int lockd_inet6addr_event(struct notifier_block *this, | ||
314 | unsigned long event, void *ptr) | ||
315 | { | ||
316 | struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; | ||
317 | struct sockaddr_in6 sin6; | ||
318 | |||
319 | if (event != NETDEV_DOWN) | ||
320 | goto out; | ||
321 | |||
322 | if (nlmsvc_rqst) { | ||
323 | dprintk("lockd_inet6addr_event: removed %pI6\n", &ifa->addr); | ||
324 | sin6.sin6_family = AF_INET6; | ||
325 | sin6.sin6_addr = ifa->addr; | ||
326 | svc_age_temp_xprts_now(nlmsvc_rqst->rq_server, | ||
327 | (struct sockaddr *)&sin6); | ||
328 | } | ||
329 | |||
330 | out: | ||
331 | return NOTIFY_DONE; | ||
332 | } | ||
333 | |||
334 | static struct notifier_block lockd_inet6addr_notifier = { | ||
335 | .notifier_call = lockd_inet6addr_event, | ||
336 | }; | ||
337 | #endif | ||
338 | |||
339 | static void lockd_svc_exit_thread(void) | ||
340 | { | ||
341 | unregister_inetaddr_notifier(&lockd_inetaddr_notifier); | ||
342 | #if IS_ENABLED(CONFIG_IPV6) | ||
343 | unregister_inet6addr_notifier(&lockd_inet6addr_notifier); | ||
344 | #endif | ||
345 | svc_exit_thread(nlmsvc_rqst); | ||
346 | } | ||
347 | |||
282 | static int lockd_start_svc(struct svc_serv *serv) | 348 | static int lockd_start_svc(struct svc_serv *serv) |
283 | { | 349 | { |
284 | int error; | 350 | int error; |
@@ -315,7 +381,7 @@ static int lockd_start_svc(struct svc_serv *serv) | |||
315 | return 0; | 381 | return 0; |
316 | 382 | ||
317 | out_task: | 383 | out_task: |
318 | svc_exit_thread(nlmsvc_rqst); | 384 | lockd_svc_exit_thread(); |
319 | nlmsvc_task = NULL; | 385 | nlmsvc_task = NULL; |
320 | out_rqst: | 386 | out_rqst: |
321 | nlmsvc_rqst = NULL; | 387 | nlmsvc_rqst = NULL; |
@@ -360,6 +426,10 @@ static struct svc_serv *lockd_create_svc(void) | |||
360 | printk(KERN_WARNING "lockd_up: create service failed\n"); | 426 | printk(KERN_WARNING "lockd_up: create service failed\n"); |
361 | return ERR_PTR(-ENOMEM); | 427 | return ERR_PTR(-ENOMEM); |
362 | } | 428 | } |
429 | register_inetaddr_notifier(&lockd_inetaddr_notifier); | ||
430 | #if IS_ENABLED(CONFIG_IPV6) | ||
431 | register_inet6addr_notifier(&lockd_inet6addr_notifier); | ||
432 | #endif | ||
363 | dprintk("lockd_up: service created\n"); | 433 | dprintk("lockd_up: service created\n"); |
364 | return serv; | 434 | return serv; |
365 | } | 435 | } |
@@ -428,7 +498,7 @@ lockd_down(struct net *net) | |||
428 | } | 498 | } |
429 | kthread_stop(nlmsvc_task); | 499 | kthread_stop(nlmsvc_task); |
430 | dprintk("lockd_down: service stopped\n"); | 500 | dprintk("lockd_down: service stopped\n"); |
431 | svc_exit_thread(nlmsvc_rqst); | 501 | lockd_svc_exit_thread(); |
432 | dprintk("lockd_down: service destroyed\n"); | 502 | dprintk("lockd_down: service destroyed\n"); |
433 | nlmsvc_task = NULL; | 503 | nlmsvc_task = NULL; |
434 | nlmsvc_rqst = NULL; | 504 | nlmsvc_rqst = NULL; |