diff options
Diffstat (limited to 'net/sunrpc/svc.c')
-rw-r--r-- | net/sunrpc/svc.c | 98 |
1 files changed, 60 insertions, 38 deletions
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index e4aabc02368b..4153846984ac 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/kthread.h> | 21 | #include <linux/kthread.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/nsproxy.h> | ||
23 | 24 | ||
24 | #include <linux/sunrpc/types.h> | 25 | #include <linux/sunrpc/types.h> |
25 | #include <linux/sunrpc/xdr.h> | 26 | #include <linux/sunrpc/xdr.h> |
@@ -30,7 +31,7 @@ | |||
30 | 31 | ||
31 | #define RPCDBG_FACILITY RPCDBG_SVCDSP | 32 | #define RPCDBG_FACILITY RPCDBG_SVCDSP |
32 | 33 | ||
33 | static void svc_unregister(const struct svc_serv *serv); | 34 | static void svc_unregister(const struct svc_serv *serv, struct net *net); |
34 | 35 | ||
35 | #define svc_serv_is_pooled(serv) ((serv)->sv_function) | 36 | #define svc_serv_is_pooled(serv) ((serv)->sv_function) |
36 | 37 | ||
@@ -368,23 +369,24 @@ svc_pool_for_cpu(struct svc_serv *serv, int cpu) | |||
368 | return &serv->sv_pools[pidx % serv->sv_nrpools]; | 369 | return &serv->sv_pools[pidx % serv->sv_nrpools]; |
369 | } | 370 | } |
370 | 371 | ||
371 | static int svc_rpcb_setup(struct svc_serv *serv) | 372 | int svc_rpcb_setup(struct svc_serv *serv, struct net *net) |
372 | { | 373 | { |
373 | int err; | 374 | int err; |
374 | 375 | ||
375 | err = rpcb_create_local(); | 376 | err = rpcb_create_local(net); |
376 | if (err) | 377 | if (err) |
377 | return err; | 378 | return err; |
378 | 379 | ||
379 | /* Remove any stale portmap registrations */ | 380 | /* Remove any stale portmap registrations */ |
380 | svc_unregister(serv); | 381 | svc_unregister(serv, net); |
381 | return 0; | 382 | return 0; |
382 | } | 383 | } |
384 | EXPORT_SYMBOL_GPL(svc_rpcb_setup); | ||
383 | 385 | ||
384 | void svc_rpcb_cleanup(struct svc_serv *serv) | 386 | void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net) |
385 | { | 387 | { |
386 | svc_unregister(serv); | 388 | svc_unregister(serv, net); |
387 | rpcb_put_local(); | 389 | rpcb_put_local(net); |
388 | } | 390 | } |
389 | EXPORT_SYMBOL_GPL(svc_rpcb_cleanup); | 391 | EXPORT_SYMBOL_GPL(svc_rpcb_cleanup); |
390 | 392 | ||
@@ -410,7 +412,7 @@ static int svc_uses_rpcbind(struct svc_serv *serv) | |||
410 | */ | 412 | */ |
411 | static struct svc_serv * | 413 | static struct svc_serv * |
412 | __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | 414 | __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, |
413 | void (*shutdown)(struct svc_serv *serv)) | 415 | void (*shutdown)(struct svc_serv *serv, struct net *net)) |
414 | { | 416 | { |
415 | struct svc_serv *serv; | 417 | struct svc_serv *serv; |
416 | unsigned int vers; | 418 | unsigned int vers; |
@@ -470,7 +472,7 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
470 | } | 472 | } |
471 | 473 | ||
472 | if (svc_uses_rpcbind(serv)) { | 474 | if (svc_uses_rpcbind(serv)) { |
473 | if (svc_rpcb_setup(serv) < 0) { | 475 | if (svc_rpcb_setup(serv, current->nsproxy->net_ns) < 0) { |
474 | kfree(serv->sv_pools); | 476 | kfree(serv->sv_pools); |
475 | kfree(serv); | 477 | kfree(serv); |
476 | return NULL; | 478 | return NULL; |
@@ -484,7 +486,7 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
484 | 486 | ||
485 | struct svc_serv * | 487 | struct svc_serv * |
486 | svc_create(struct svc_program *prog, unsigned int bufsize, | 488 | svc_create(struct svc_program *prog, unsigned int bufsize, |
487 | void (*shutdown)(struct svc_serv *serv)) | 489 | void (*shutdown)(struct svc_serv *serv, struct net *net)) |
488 | { | 490 | { |
489 | return __svc_create(prog, bufsize, /*npools*/1, shutdown); | 491 | return __svc_create(prog, bufsize, /*npools*/1, shutdown); |
490 | } | 492 | } |
@@ -492,7 +494,7 @@ EXPORT_SYMBOL_GPL(svc_create); | |||
492 | 494 | ||
493 | struct svc_serv * | 495 | struct svc_serv * |
494 | svc_create_pooled(struct svc_program *prog, unsigned int bufsize, | 496 | svc_create_pooled(struct svc_program *prog, unsigned int bufsize, |
495 | void (*shutdown)(struct svc_serv *serv), | 497 | void (*shutdown)(struct svc_serv *serv, struct net *net), |
496 | svc_thread_fn func, struct module *mod) | 498 | svc_thread_fn func, struct module *mod) |
497 | { | 499 | { |
498 | struct svc_serv *serv; | 500 | struct svc_serv *serv; |
@@ -509,6 +511,24 @@ svc_create_pooled(struct svc_program *prog, unsigned int bufsize, | |||
509 | } | 511 | } |
510 | EXPORT_SYMBOL_GPL(svc_create_pooled); | 512 | EXPORT_SYMBOL_GPL(svc_create_pooled); |
511 | 513 | ||
514 | void svc_shutdown_net(struct svc_serv *serv, struct net *net) | ||
515 | { | ||
516 | /* | ||
517 | * The set of xprts (contained in the sv_tempsocks and | ||
518 | * sv_permsocks lists) is now constant, since it is modified | ||
519 | * only by accepting new sockets (done by service threads in | ||
520 | * svc_recv) or aging old ones (done by sv_temptimer), or | ||
521 | * configuration changes (excluded by whatever locking the | ||
522 | * caller is using--nfsd_mutex in the case of nfsd). So it's | ||
523 | * safe to traverse those lists and shut everything down: | ||
524 | */ | ||
525 | svc_close_net(serv, net); | ||
526 | |||
527 | if (serv->sv_shutdown) | ||
528 | serv->sv_shutdown(serv, net); | ||
529 | } | ||
530 | EXPORT_SYMBOL_GPL(svc_shutdown_net); | ||
531 | |||
512 | /* | 532 | /* |
513 | * Destroy an RPC service. Should be called with appropriate locking to | 533 | * Destroy an RPC service. Should be called with appropriate locking to |
514 | * protect the sv_nrthreads, sv_permsocks and sv_tempsocks. | 534 | * protect the sv_nrthreads, sv_permsocks and sv_tempsocks. |
@@ -516,6 +536,8 @@ EXPORT_SYMBOL_GPL(svc_create_pooled); | |||
516 | void | 536 | void |
517 | svc_destroy(struct svc_serv *serv) | 537 | svc_destroy(struct svc_serv *serv) |
518 | { | 538 | { |
539 | struct net *net = current->nsproxy->net_ns; | ||
540 | |||
519 | dprintk("svc: svc_destroy(%s, %d)\n", | 541 | dprintk("svc: svc_destroy(%s, %d)\n", |
520 | serv->sv_program->pg_name, | 542 | serv->sv_program->pg_name, |
521 | serv->sv_nrthreads); | 543 | serv->sv_nrthreads); |
@@ -529,19 +551,15 @@ svc_destroy(struct svc_serv *serv) | |||
529 | printk("svc_destroy: no threads for serv=%p!\n", serv); | 551 | printk("svc_destroy: no threads for serv=%p!\n", serv); |
530 | 552 | ||
531 | del_timer_sync(&serv->sv_temptimer); | 553 | del_timer_sync(&serv->sv_temptimer); |
554 | |||
555 | svc_shutdown_net(serv, net); | ||
556 | |||
532 | /* | 557 | /* |
533 | * The set of xprts (contained in the sv_tempsocks and | 558 | * The last user is gone and thus all sockets have to be destroyed to |
534 | * sv_permsocks lists) is now constant, since it is modified | 559 | * the point. Check this. |
535 | * only by accepting new sockets (done by service threads in | ||
536 | * svc_recv) or aging old ones (done by sv_temptimer), or | ||
537 | * configuration changes (excluded by whatever locking the | ||
538 | * caller is using--nfsd_mutex in the case of nfsd). So it's | ||
539 | * safe to traverse those lists and shut everything down: | ||
540 | */ | 560 | */ |
541 | svc_close_all(serv); | 561 | BUG_ON(!list_empty(&serv->sv_permsocks)); |
542 | 562 | BUG_ON(!list_empty(&serv->sv_tempsocks)); | |
543 | if (serv->sv_shutdown) | ||
544 | serv->sv_shutdown(serv); | ||
545 | 563 | ||
546 | cache_clean_deferred(serv); | 564 | cache_clean_deferred(serv); |
547 | 565 | ||
@@ -795,7 +813,8 @@ EXPORT_SYMBOL_GPL(svc_exit_thread); | |||
795 | * Returns zero on success; a negative errno value is returned | 813 | * Returns zero on success; a negative errno value is returned |
796 | * if any error occurs. | 814 | * if any error occurs. |
797 | */ | 815 | */ |
798 | static int __svc_rpcb_register4(const u32 program, const u32 version, | 816 | static int __svc_rpcb_register4(struct net *net, const u32 program, |
817 | const u32 version, | ||
799 | const unsigned short protocol, | 818 | const unsigned short protocol, |
800 | const unsigned short port) | 819 | const unsigned short port) |
801 | { | 820 | { |
@@ -818,7 +837,7 @@ static int __svc_rpcb_register4(const u32 program, const u32 version, | |||
818 | return -ENOPROTOOPT; | 837 | return -ENOPROTOOPT; |
819 | } | 838 | } |
820 | 839 | ||
821 | error = rpcb_v4_register(program, version, | 840 | error = rpcb_v4_register(net, program, version, |
822 | (const struct sockaddr *)&sin, netid); | 841 | (const struct sockaddr *)&sin, netid); |
823 | 842 | ||
824 | /* | 843 | /* |
@@ -826,7 +845,7 @@ static int __svc_rpcb_register4(const u32 program, const u32 version, | |||
826 | * registration request with the legacy rpcbind v2 protocol. | 845 | * registration request with the legacy rpcbind v2 protocol. |
827 | */ | 846 | */ |
828 | if (error == -EPROTONOSUPPORT) | 847 | if (error == -EPROTONOSUPPORT) |
829 | error = rpcb_register(program, version, protocol, port); | 848 | error = rpcb_register(net, program, version, protocol, port); |
830 | 849 | ||
831 | return error; | 850 | return error; |
832 | } | 851 | } |
@@ -842,7 +861,8 @@ static int __svc_rpcb_register4(const u32 program, const u32 version, | |||
842 | * Returns zero on success; a negative errno value is returned | 861 | * Returns zero on success; a negative errno value is returned |
843 | * if any error occurs. | 862 | * if any error occurs. |
844 | */ | 863 | */ |
845 | static int __svc_rpcb_register6(const u32 program, const u32 version, | 864 | static int __svc_rpcb_register6(struct net *net, const u32 program, |
865 | const u32 version, | ||
846 | const unsigned short protocol, | 866 | const unsigned short protocol, |
847 | const unsigned short port) | 867 | const unsigned short port) |
848 | { | 868 | { |
@@ -865,7 +885,7 @@ static int __svc_rpcb_register6(const u32 program, const u32 version, | |||
865 | return -ENOPROTOOPT; | 885 | return -ENOPROTOOPT; |
866 | } | 886 | } |
867 | 887 | ||
868 | error = rpcb_v4_register(program, version, | 888 | error = rpcb_v4_register(net, program, version, |
869 | (const struct sockaddr *)&sin6, netid); | 889 | (const struct sockaddr *)&sin6, netid); |
870 | 890 | ||
871 | /* | 891 | /* |
@@ -885,7 +905,7 @@ static int __svc_rpcb_register6(const u32 program, const u32 version, | |||
885 | * Returns zero on success; a negative errno value is returned | 905 | * Returns zero on success; a negative errno value is returned |
886 | * if any error occurs. | 906 | * if any error occurs. |
887 | */ | 907 | */ |
888 | static int __svc_register(const char *progname, | 908 | static int __svc_register(struct net *net, const char *progname, |
889 | const u32 program, const u32 version, | 909 | const u32 program, const u32 version, |
890 | const int family, | 910 | const int family, |
891 | const unsigned short protocol, | 911 | const unsigned short protocol, |
@@ -895,12 +915,12 @@ static int __svc_register(const char *progname, | |||
895 | 915 | ||
896 | switch (family) { | 916 | switch (family) { |
897 | case PF_INET: | 917 | case PF_INET: |
898 | error = __svc_rpcb_register4(program, version, | 918 | error = __svc_rpcb_register4(net, program, version, |
899 | protocol, port); | 919 | protocol, port); |
900 | break; | 920 | break; |
901 | #if IS_ENABLED(CONFIG_IPV6) | 921 | #if IS_ENABLED(CONFIG_IPV6) |
902 | case PF_INET6: | 922 | case PF_INET6: |
903 | error = __svc_rpcb_register6(program, version, | 923 | error = __svc_rpcb_register6(net, program, version, |
904 | protocol, port); | 924 | protocol, port); |
905 | #endif | 925 | #endif |
906 | } | 926 | } |
@@ -914,14 +934,16 @@ static int __svc_register(const char *progname, | |||
914 | /** | 934 | /** |
915 | * svc_register - register an RPC service with the local portmapper | 935 | * svc_register - register an RPC service with the local portmapper |
916 | * @serv: svc_serv struct for the service to register | 936 | * @serv: svc_serv struct for the service to register |
937 | * @net: net namespace for the service to register | ||
917 | * @family: protocol family of service's listener socket | 938 | * @family: protocol family of service's listener socket |
918 | * @proto: transport protocol number to advertise | 939 | * @proto: transport protocol number to advertise |
919 | * @port: port to advertise | 940 | * @port: port to advertise |
920 | * | 941 | * |
921 | * Service is registered for any address in the passed-in protocol family | 942 | * Service is registered for any address in the passed-in protocol family |
922 | */ | 943 | */ |
923 | int svc_register(const struct svc_serv *serv, const int family, | 944 | int svc_register(const struct svc_serv *serv, struct net *net, |
924 | const unsigned short proto, const unsigned short port) | 945 | const int family, const unsigned short proto, |
946 | const unsigned short port) | ||
925 | { | 947 | { |
926 | struct svc_program *progp; | 948 | struct svc_program *progp; |
927 | unsigned int i; | 949 | unsigned int i; |
@@ -946,7 +968,7 @@ int svc_register(const struct svc_serv *serv, const int family, | |||
946 | if (progp->pg_vers[i]->vs_hidden) | 968 | if (progp->pg_vers[i]->vs_hidden) |
947 | continue; | 969 | continue; |
948 | 970 | ||
949 | error = __svc_register(progp->pg_name, progp->pg_prog, | 971 | error = __svc_register(net, progp->pg_name, progp->pg_prog, |
950 | i, family, proto, port); | 972 | i, family, proto, port); |
951 | if (error < 0) | 973 | if (error < 0) |
952 | break; | 974 | break; |
@@ -963,19 +985,19 @@ int svc_register(const struct svc_serv *serv, const int family, | |||
963 | * any "inet6" entries anyway. So a PMAP_UNSET should be sufficient | 985 | * any "inet6" entries anyway. So a PMAP_UNSET should be sufficient |
964 | * in this case to clear all existing entries for [program, version]. | 986 | * in this case to clear all existing entries for [program, version]. |
965 | */ | 987 | */ |
966 | static void __svc_unregister(const u32 program, const u32 version, | 988 | static void __svc_unregister(struct net *net, const u32 program, const u32 version, |
967 | const char *progname) | 989 | const char *progname) |
968 | { | 990 | { |
969 | int error; | 991 | int error; |
970 | 992 | ||
971 | error = rpcb_v4_register(program, version, NULL, ""); | 993 | error = rpcb_v4_register(net, program, version, NULL, ""); |
972 | 994 | ||
973 | /* | 995 | /* |
974 | * User space didn't support rpcbind v4, so retry this | 996 | * User space didn't support rpcbind v4, so retry this |
975 | * request with the legacy rpcbind v2 protocol. | 997 | * request with the legacy rpcbind v2 protocol. |
976 | */ | 998 | */ |
977 | if (error == -EPROTONOSUPPORT) | 999 | if (error == -EPROTONOSUPPORT) |
978 | error = rpcb_register(program, version, 0, 0); | 1000 | error = rpcb_register(net, program, version, 0, 0); |
979 | 1001 | ||
980 | dprintk("svc: %s(%sv%u), error %d\n", | 1002 | dprintk("svc: %s(%sv%u), error %d\n", |
981 | __func__, progname, version, error); | 1003 | __func__, progname, version, error); |
@@ -989,7 +1011,7 @@ static void __svc_unregister(const u32 program, const u32 version, | |||
989 | * The result of unregistration is reported via dprintk for those who want | 1011 | * The result of unregistration is reported via dprintk for those who want |
990 | * verification of the result, but is otherwise not important. | 1012 | * verification of the result, but is otherwise not important. |
991 | */ | 1013 | */ |
992 | static void svc_unregister(const struct svc_serv *serv) | 1014 | static void svc_unregister(const struct svc_serv *serv, struct net *net) |
993 | { | 1015 | { |
994 | struct svc_program *progp; | 1016 | struct svc_program *progp; |
995 | unsigned long flags; | 1017 | unsigned long flags; |
@@ -1006,7 +1028,7 @@ static void svc_unregister(const struct svc_serv *serv) | |||
1006 | 1028 | ||
1007 | dprintk("svc: attempting to unregister %sv%u\n", | 1029 | dprintk("svc: attempting to unregister %sv%u\n", |
1008 | progp->pg_name, i); | 1030 | progp->pg_name, i); |
1009 | __svc_unregister(progp->pg_prog, i, progp->pg_name); | 1031 | __svc_unregister(net, progp->pg_prog, i, progp->pg_name); |
1010 | } | 1032 | } |
1011 | } | 1033 | } |
1012 | 1034 | ||