Commit eb16e907781a9da7f272a3e8284c26bc4e4aeb9d

Authored by Chuck Lever
Committed by Trond Myklebust
1 parent 9355982830

lockd: Start PF_INET6 listener only if IPv6 support is available

Apparently a lot of people need to disable IPv6 completely on their
distributor-built systems, which have CONFIG_IPV6_MODULE enabled at
build time.

They do this by blacklisting the ipv6.ko module.  This causes the
creation of the lockd service listener to fail if CONFIG_IPV6_MODULE
is set, but the module cannot be loaded.

Now that the kernel's PF_INET6 RPC listeners are completely separate
from PF_INET listeners, we can always start PF_INET.  Then lockd can
try to start PF_INET6, but it isn't required to be available.

Note this has the added benefit that NLM callbacks from AF_INET6
servers will never come from AF_INET remotes.  We no longer have to
worry about matching mapped IPv4 addresses to AF_INET when comparing
addresses.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

Showing 2 changed files with 22 additions and 59 deletions Side-by-side Diff

... ... @@ -139,56 +139,7 @@
139 139 return 0;
140 140 }
141 141  
142   -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
143   -static const struct in6_addr *nlmclnt_map_v4addr(const struct sockaddr *sap,
144   - struct in6_addr *addr_mapped)
145   -{
146   - const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
147   -
148   - switch (sap->sa_family) {
149   - case AF_INET6:
150   - return &((const struct sockaddr_in6 *)sap)->sin6_addr;
151   - case AF_INET:
152   - ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, addr_mapped);
153   - return addr_mapped;
154   - }
155   -
156   - return NULL;
157   -}
158   -
159 142 /*
160   - * If lockd is using a PF_INET6 listener, all incoming requests appear
161   - * to come from AF_INET6 remotes. The address of AF_INET remotes are
162   - * mapped to AF_INET6 automatically by the network layer. In case the
163   - * user passed an AF_INET server address at mount time, ensure both
164   - * addresses are AF_INET6 before comparing them.
165   - */
166   -static int nlmclnt_cmp_addr(const struct nlm_host *host,
167   - const struct sockaddr *sap)
168   -{
169   - const struct in6_addr *addr1;
170   - const struct in6_addr *addr2;
171   - struct in6_addr addr1_mapped;
172   - struct in6_addr addr2_mapped;
173   -
174   - addr1 = nlmclnt_map_v4addr(nlm_addr(host), &addr1_mapped);
175   - if (likely(addr1 != NULL)) {
176   - addr2 = nlmclnt_map_v4addr(sap, &addr2_mapped);
177   - if (likely(addr2 != NULL))
178   - return ipv6_addr_equal(addr1, addr2);
179   - }
180   -
181   - return 0;
182   -}
183   -#else /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
184   -static int nlmclnt_cmp_addr(const struct nlm_host *host,
185   - const struct sockaddr *sap)
186   -{
187   - return nlm_cmp_addr(nlm_addr(host), sap);
188   -}
189   -#endif /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
190   -
191   -/*
192 143 * The server lockd has called us back to tell us the lock was granted
193 144 */
194 145 __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
... ... @@ -215,7 +166,7 @@
215 166 */
216 167 if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid)
217 168 continue;
218   - if (!nlmclnt_cmp_addr(block->b_host, addr))
  169 + if (!nlm_cmp_addr(nlm_addr(block->b_host), addr))
219 170 continue;
220 171 if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0)
221 172 continue;
... ... @@ -193,20 +193,30 @@
193 193 return 0;
194 194 }
195 195  
196   -static int create_lockd_listener(struct svc_serv *serv, char *name,
197   - unsigned short port)
  196 +static int create_lockd_listener(struct svc_serv *serv, const char *name,
  197 + const int family, const unsigned short port)
198 198 {
199 199 struct svc_xprt *xprt;
200 200  
201   - xprt = svc_find_xprt(serv, name, 0, 0);
  201 + xprt = svc_find_xprt(serv, name, family, 0);
202 202 if (xprt == NULL)
203   - return svc_create_xprt(serv, name, PF_INET,
204   - port, SVC_SOCK_DEFAULTS);
205   -
  203 + return svc_create_xprt(serv, name, family, port,
  204 + SVC_SOCK_DEFAULTS);
206 205 svc_xprt_put(xprt);
207 206 return 0;
208 207 }
209 208  
  209 +static int create_lockd_family(struct svc_serv *serv, const int family)
  210 +{
  211 + int err;
  212 +
  213 + err = create_lockd_listener(serv, "udp", family, nlm_udpport);
  214 + if (err < 0)
  215 + return err;
  216 +
  217 + return create_lockd_listener(serv, "tcp", family, nlm_tcpport);
  218 +}
  219 +
210 220 /*
211 221 * Ensure there are active UDP and TCP listeners for lockd.
212 222 *
213 223  
214 224  
... ... @@ -222,13 +232,15 @@
222 232 static int warned;
223 233 int err;
224 234  
225   - err = create_lockd_listener(serv, "udp", nlm_udpport);
  235 + err = create_lockd_family(serv, PF_INET);
226 236 if (err < 0)
227 237 goto out_err;
228 238  
229   - err = create_lockd_listener(serv, "tcp", nlm_tcpport);
230   - if (err < 0)
  239 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  240 + err = create_lockd_family(serv, PF_INET6);
  241 + if (err < 0 && err != -EAFNOSUPPORT)
231 242 goto out_err;
  243 +#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
232 244  
233 245 warned = 0;
234 246 return 0;