Commit eb16e907781a9da7f272a3e8284c26bc4e4aeb9d
Committed by
Trond Myklebust
1 parent
9355982830
Exists in
master
and in
4 other branches
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
fs/lockd/clntlock.c
... | ... | @@ -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; |
fs/lockd/svc.c
... | ... | @@ -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; |