diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2008-08-18 19:34:08 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2008-09-29 18:13:38 -0400 |
commit | 7252d575ab0e8771269a3d245c36a05ace5152bd (patch) | |
tree | e3a60421367bd4a2a01b823772dc40a2af64960a /net | |
parent | 14aeb2118d6e9fd9ee988324c740a00c80979093 (diff) |
SUNRPC: Split portmap unregister API into separate function
Create a separate server-level interface for unregistering RPC services.
The mechanics of, and the API for, registering and unregistering RPC
services will diverge further as support for IPv6 is added.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/svc.c | 62 |
1 files changed, 50 insertions, 12 deletions
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 9805143d0660..9eb78a771da5 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -28,6 +28,8 @@ | |||
28 | 28 | ||
29 | #define RPCDBG_FACILITY RPCDBG_SVCDSP | 29 | #define RPCDBG_FACILITY RPCDBG_SVCDSP |
30 | 30 | ||
31 | static void svc_unregister(const struct svc_serv *serv); | ||
32 | |||
31 | #define svc_serv_is_pooled(serv) ((serv)->sv_function) | 33 | #define svc_serv_is_pooled(serv) ((serv)->sv_function) |
32 | 34 | ||
33 | /* | 35 | /* |
@@ -417,9 +419,8 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
417 | spin_lock_init(&pool->sp_lock); | 419 | spin_lock_init(&pool->sp_lock); |
418 | } | 420 | } |
419 | 421 | ||
420 | |||
421 | /* Remove any stale portmap registrations */ | 422 | /* Remove any stale portmap registrations */ |
422 | svc_register(serv, 0, 0); | 423 | svc_unregister(serv); |
423 | 424 | ||
424 | return serv; | 425 | return serv; |
425 | } | 426 | } |
@@ -487,8 +488,7 @@ svc_destroy(struct svc_serv *serv) | |||
487 | if (svc_serv_is_pooled(serv)) | 488 | if (svc_serv_is_pooled(serv)) |
488 | svc_pool_map_put(); | 489 | svc_pool_map_put(); |
489 | 490 | ||
490 | /* Unregister service with the portmapper */ | 491 | svc_unregister(serv); |
491 | svc_register(serv, 0, 0); | ||
492 | kfree(serv->sv_pools); | 492 | kfree(serv->sv_pools); |
493 | kfree(serv); | 493 | kfree(serv); |
494 | } | 494 | } |
@@ -728,12 +728,10 @@ int | |||
728 | svc_register(struct svc_serv *serv, int proto, unsigned short port) | 728 | svc_register(struct svc_serv *serv, int proto, unsigned short port) |
729 | { | 729 | { |
730 | struct svc_program *progp; | 730 | struct svc_program *progp; |
731 | unsigned long flags; | ||
732 | unsigned int i; | 731 | unsigned int i; |
733 | int error = 0; | 732 | int error = 0; |
734 | 733 | ||
735 | if (!port) | 734 | BUG_ON(proto == 0 && port == 0); |
736 | clear_thread_flag(TIF_SIGPENDING); | ||
737 | 735 | ||
738 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { | 736 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { |
739 | for (i = 0; i < progp->pg_nvers; i++) { | 737 | for (i = 0; i < progp->pg_nvers; i++) { |
@@ -757,13 +755,53 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port) | |||
757 | } | 755 | } |
758 | } | 756 | } |
759 | 757 | ||
760 | if (!port) { | 758 | return error; |
761 | spin_lock_irqsave(¤t->sighand->siglock, flags); | 759 | } |
762 | recalc_sigpending(); | 760 | |
763 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | 761 | /* |
762 | * All transport protocols and ports for this service are removed | ||
763 | * from the local rpcbind database if the service is not hidden. | ||
764 | * | ||
765 | * The result of unregistration is reported via dprintk for those | ||
766 | * who want verification of the result, but is otherwise not | ||
767 | * important. | ||
768 | * | ||
769 | * The local rpcbind daemon listens on either only IPv6 or only | ||
770 | * IPv4. The kernel can't tell how it's configured. However, | ||
771 | * AF_INET addresses are mapped to AF_INET6 in IPv6-only config- | ||
772 | * urations, so even an unregistration request on AF_INET will | ||
773 | * get to a local rpcbind daemon listening only on AF_INET6. So | ||
774 | * we always unregister via AF_INET. | ||
775 | * | ||
776 | * At this point we don't need rpcbind version 4 for unregis- | ||
777 | * tration: A v2 UNSET request will clear all transports (netids), | ||
778 | * addresses, and address families for [program, version]. | ||
779 | */ | ||
780 | static void svc_unregister(const struct svc_serv *serv) | ||
781 | { | ||
782 | struct svc_program *progp; | ||
783 | unsigned long flags; | ||
784 | unsigned int i; | ||
785 | int error; | ||
786 | |||
787 | clear_thread_flag(TIF_SIGPENDING); | ||
788 | |||
789 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { | ||
790 | for (i = 0; i < progp->pg_nvers; i++) { | ||
791 | if (progp->pg_vers[i] == NULL) | ||
792 | continue; | ||
793 | if (progp->pg_vers[i]->vs_hidden) | ||
794 | continue; | ||
795 | |||
796 | error = rpcb_register(progp->pg_prog, i, 0, 0); | ||
797 | dprintk("svc: svc_unregister(%sv%u), error %d\n", | ||
798 | progp->pg_name, i, error); | ||
799 | } | ||
764 | } | 800 | } |
765 | 801 | ||
766 | return error; | 802 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
803 | recalc_sigpending(); | ||
804 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | ||
767 | } | 805 | } |
768 | 806 | ||
769 | /* | 807 | /* |