Commit f6fb3f6f591b50fa4f51962ad06ee0d8782e1bc8
Committed by
J. Bruce Fields
1 parent
9d548b9c95
Exists in
master
and in
7 other branches
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>
Showing 1 changed file with 38 additions and 20 deletions Side-by-side Diff
net/sunrpc/svc.c
... | ... | @@ -896,31 +896,51 @@ |
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 | |
... | ... | @@ -931,9 +951,7 @@ |
931 | 951 | if (progp->pg_vers[i]->vs_hidden) |
932 | 952 | continue; |
933 | 953 | |
934 | - error = rpcb_register(progp->pg_prog, i, 0, 0); | |
935 | - dprintk("svc: svc_unregister(%sv%u), error %d\n", | |
936 | - progp->pg_name, i, error); | |
954 | + __svc_unregister(progp->pg_prog, i, progp->pg_name); | |
937 | 955 | } |
938 | 956 | } |
939 | 957 |