Detect the case where we sent an rpcbind v4 UNSET but user space doesn't support rpcbind protocol version 4. We down-shift to version 2 and print a warning once in this case. Olaf says a v2 UNSET should properly clear all entries in the rpcbind database. As svc_unregister() is usually done first to clear old portmapper entries before trying to set up new ones, a v4 UNSET call will almost always be the first to detect an rpcbind protocol version mismatch problem. Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> --- net/sunrpc/svc.c | 51 ++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 44 insertions(+), 7 deletions(-) diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index a278a82..e93bc55 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -721,6 +721,21 @@ EXPORT_SYMBOL_GPL(svc_exit_thread); #ifdef CONFIG_SUNRPC_REGISTER_V4 +static u32 __svc_register_version = 4; + +static void __svc_rpcb_prog_mismatch_error(void) +{ + if (__svc_register_version == 4) { + printk(KERN_WARNING + "svc: The kernel tried an rpcbind version 4 request, " + "but your portmapper\n" + "svc: does not support rpcbind version 4. " + "Switching to rpcbind version 2.\n"); + + __svc_register_version = 2; + } +} + /* * Register an "inet" protocol family netid with the local * rpcbind daemon via an rpcbind v4 SET request. @@ -896,10 +911,20 @@ int svc_register(const struct svc_serv *serv, const unsigned short proto, return error; } +static void __svc_v2_unregister(const u32 program, const u32 version, + const char *progname) +{ + int error; + + error = rpcb_register(program, version, 0, 0); + dprintk("svc: %s(%sv%u), error %d\n", + __func__, progname, version, error); +} + #ifdef CONFIG_SUNRPC_REGISTER_V4 -static void __svc_unregister(const u32 program, const u32 version, - const char *progname) +static int __svc_v4_unregister(const u32 program, const u32 version, + const char *progname) { struct sockaddr_in6 sin6 = { .sin6_family = AF_INET6, @@ -912,6 +937,22 @@ static void __svc_unregister(const u32 program, const u32 version, (struct sockaddr *)&sin6, ""); dprintk("svc: %s(%sv%u), error %d\n", __func__, progname, version, error); + return error; +} + +static void __svc_unregister(const u32 program, const u32 version, + const char *progname) +{ + if (__svc_register_version == 4) { + int error = __svc_v4_unregister(program, version, progname); + if (error != -EPROTONOSUPPORT) + return; + } + + __svc_rpcb_prog_mismatch_error(); + + /* Olaf says a v2 UNSET _should_ wipe everything */ + __svc_v2_unregister(program, version, progname); } #else /* CONFIG_SUNRPC_REGISTER_V4 */ @@ -919,11 +960,7 @@ static void __svc_unregister(const u32 program, const u32 version, static void __svc_unregister(const u32 program, const u32 version, const char *progname) { - int error; - - error = rpcb_register(program, version, 0, 0); - dprintk("svc: %s(%sv%u), error %d\n", - __func__, progname, version, error); + __svc_v2_unregister(program, version, progname); } #endif /* CONFIG_SUNRPC_REGISTER_V4 */ -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html