Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

SUNRPC: Fix up svc_unregister()

With the new rpcbind code, a PMAP_UNSET will not have any effect on
services registered via rpcbind v3 or v4.

Implement a version of svc_unregister() that uses an RPCB_UNSET with
an empty netid string to make sure we have cleared *all* entries for
a kernel RPC service when shutting down, or before starting a fresh
instance of the service.

Use the new version only when CONFIG_SUNRPC_REGISTER_V4 is enabled;
otherwise, the legacy PMAP version is used to ensure complete
backwards-compatibility with the Linux portmapper daemon.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>

authored by

Chuck Lever and committed by
J. Bruce Fields
f6fb3f6f 9d548b9c

+38 -20
+38 -20
net/sunrpc/svc.c
··· 896 896 return error; 897 897 } 898 898 899 + #ifdef CONFIG_SUNRPC_REGISTER_V4 900 + 901 + static void __svc_unregister(const u32 program, const u32 version, 902 + const char *progname) 903 + { 904 + struct sockaddr_in6 sin6 = { 905 + .sin6_family = AF_INET6, 906 + .sin6_addr = IN6ADDR_ANY_INIT, 907 + .sin6_port = 0, 908 + }; 909 + int error; 910 + 911 + error = rpcb_v4_register(program, version, 912 + (struct sockaddr *)&sin6, ""); 913 + dprintk("svc: %s(%sv%u), error %d\n", 914 + __func__, progname, version, error); 915 + } 916 + 917 + #else /* CONFIG_SUNRPC_REGISTER_V4 */ 918 + 919 + static void __svc_unregister(const u32 program, const u32 version, 920 + const char *progname) 921 + { 922 + int error; 923 + 924 + error = rpcb_register(program, version, 0, 0); 925 + dprintk("svc: %s(%sv%u), error %d\n", 926 + __func__, progname, version, error); 927 + } 928 + 929 + #endif /* CONFIG_SUNRPC_REGISTER_V4 */ 930 + 899 931 /* 900 - * All transport protocols and ports for this service are removed 901 - * from the local rpcbind database if the service is not hidden. 932 + * All netids, bind addresses and ports registered for [program, version] 933 + * are removed from the local rpcbind database (if the service is not 934 + * hidden) to make way for a new instance of the service. 902 935 * 903 - * The result of unregistration is reported via dprintk for those 904 - * who want verification of the result, but is otherwise not 905 - * important. 906 - * 907 - * The local rpcbind daemon listens on either only IPv6 or only 908 - * IPv4. The kernel can't tell how it's configured. However, 909 - * AF_INET addresses are mapped to AF_INET6 in IPv6-only config- 910 - * urations, so even an unregistration request on AF_INET will 911 - * get to a local rpcbind daemon listening only on AF_INET6. So 912 - * we always unregister via AF_INET. 913 - * 914 - * At this point we don't need rpcbind version 4 for unregis- 915 - * tration: A v2 UNSET request will clear all transports (netids), 916 - * addresses, and address families for [program, version]. 936 + * The result of unregistration is reported via dprintk for those who want 937 + * verification of the result, but is otherwise not important. 917 938 */ 918 939 static void svc_unregister(const struct svc_serv *serv) 919 940 { 920 941 struct svc_program *progp; 921 942 unsigned long flags; 922 943 unsigned int i; 923 - int error; 924 944 925 945 clear_thread_flag(TIF_SIGPENDING); 926 946 ··· 951 931 if (progp->pg_vers[i]->vs_hidden) 952 932 continue; 953 933 954 - error = rpcb_register(progp->pg_prog, i, 0, 0); 955 - dprintk("svc: svc_unregister(%sv%u), error %d\n", 956 - progp->pg_name, i, error); 934 + __svc_unregister(progp->pg_prog, i, progp->pg_name); 957 935 } 958 936 } 959 937