From a72c4e5bc67b4945895026b3a9943a2ec1af594a Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 18 Aug 2008 19:34:08 -0400 Subject: [PATCH] --- yaml --- r: 114315 b: refs/heads/master c: 7252d575ab0e8771269a3d245c36a05ace5152bd h: refs/heads/master i: 114313: 7ac33a3c9c3035ec55b31c4e19079ce0ffde314e 114311: f6dc6644fc8d52432f3f06171fea00ef897679c7 v: v3 --- [refs] | 2 +- trunk/net/sunrpc/svc.c | 62 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/[refs] b/[refs] index 3e08160c8632..4dffa337dacb 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 14aeb2118d6e9fd9ee988324c740a00c80979093 +refs/heads/master: 7252d575ab0e8771269a3d245c36a05ace5152bd diff --git a/trunk/net/sunrpc/svc.c b/trunk/net/sunrpc/svc.c index 9805143d0660..9eb78a771da5 100644 --- a/trunk/net/sunrpc/svc.c +++ b/trunk/net/sunrpc/svc.c @@ -28,6 +28,8 @@ #define RPCDBG_FACILITY RPCDBG_SVCDSP +static void svc_unregister(const struct svc_serv *serv); + #define svc_serv_is_pooled(serv) ((serv)->sv_function) /* @@ -417,9 +419,8 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, spin_lock_init(&pool->sp_lock); } - /* Remove any stale portmap registrations */ - svc_register(serv, 0, 0); + svc_unregister(serv); return serv; } @@ -487,8 +488,7 @@ svc_destroy(struct svc_serv *serv) if (svc_serv_is_pooled(serv)) svc_pool_map_put(); - /* Unregister service with the portmapper */ - svc_register(serv, 0, 0); + svc_unregister(serv); kfree(serv->sv_pools); kfree(serv); } @@ -728,12 +728,10 @@ int svc_register(struct svc_serv *serv, int proto, unsigned short port) { struct svc_program *progp; - unsigned long flags; unsigned int i; int error = 0; - if (!port) - clear_thread_flag(TIF_SIGPENDING); + BUG_ON(proto == 0 && port == 0); for (progp = serv->sv_program; progp; progp = progp->pg_next) { for (i = 0; i < progp->pg_nvers; i++) { @@ -757,13 +755,53 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port) } } - if (!port) { - spin_lock_irqsave(¤t->sighand->siglock, flags); - recalc_sigpending(); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); + return error; +} + +/* + * All transport protocols and ports for this service are removed + * from the local rpcbind database if the service is not hidden. + * + * The result of unregistration is reported via dprintk for those + * who want verification of the result, but is otherwise not + * important. + * + * The local rpcbind daemon listens on either only IPv6 or only + * IPv4. The kernel can't tell how it's configured. However, + * AF_INET addresses are mapped to AF_INET6 in IPv6-only config- + * urations, so even an unregistration request on AF_INET will + * get to a local rpcbind daemon listening only on AF_INET6. So + * we always unregister via AF_INET. + * + * At this point we don't need rpcbind version 4 for unregis- + * tration: A v2 UNSET request will clear all transports (netids), + * addresses, and address families for [program, version]. + */ +static void svc_unregister(const struct svc_serv *serv) +{ + struct svc_program *progp; + unsigned long flags; + unsigned int i; + int error; + + clear_thread_flag(TIF_SIGPENDING); + + for (progp = serv->sv_program; progp; progp = progp->pg_next) { + for (i = 0; i < progp->pg_nvers; i++) { + if (progp->pg_vers[i] == NULL) + continue; + if (progp->pg_vers[i]->vs_hidden) + continue; + + error = rpcb_register(progp->pg_prog, i, 0, 0); + dprintk("svc: svc_unregister(%sv%u), error %d\n", + progp->pg_name, i, error); + } } - return error; + spin_lock_irqsave(¤t->sighand->siglock, flags); + recalc_sigpending(); + spin_unlock_irqrestore(¤t->sighand->siglock, flags); } /*