Blame view
fs/lockd/host.c
17.5 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 8 9 10 11 12 |
/* * linux/fs/lockd/host.c * * Management for NLM peer hosts. The nlm_host struct is shared * between client and server implementation. The only reason to * do so is to reduce code bloat. * * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> */ #include <linux/types.h> |
1da177e4c Linux-2.6.12-rc2 |
13 14 |
#include <linux/slab.h> #include <linux/in.h> |
1b333c54a lockd: address-fa... |
15 |
#include <linux/in6.h> |
1da177e4c Linux-2.6.12-rc2 |
16 |
#include <linux/sunrpc/clnt.h> |
5976687a2 sunrpc: move addr... |
17 |
#include <linux/sunrpc/addr.h> |
1da177e4c Linux-2.6.12-rc2 |
18 19 |
#include <linux/sunrpc/svc.h> #include <linux/lockd/lockd.h> |
353ab6e97 [PATCH] sem2mutex... |
20 |
#include <linux/mutex.h> |
1da177e4c Linux-2.6.12-rc2 |
21 |
|
66697bfd6 LockD: make nlm h... |
22 |
#include <linux/sunrpc/svc_xprt.h> |
1b333c54a lockd: address-fa... |
23 |
#include <net/ipv6.h> |
1da177e4c Linux-2.6.12-rc2 |
24 |
|
3cf7fb07e LockD: manage gar... |
25 |
#include "netns.h" |
1da177e4c Linux-2.6.12-rc2 |
26 |
#define NLMDBG_FACILITY NLMDBG_HOSTCACHE |
1da177e4c Linux-2.6.12-rc2 |
27 |
#define NLM_HOST_NRHASH 32 |
1da177e4c Linux-2.6.12-rc2 |
28 |
#define NLM_HOST_REBIND (60 * HZ) |
1447d25eb knfsd: Remove NLM... |
29 30 |
#define NLM_HOST_EXPIRE (300 * HZ) #define NLM_HOST_COLLECT (120 * HZ) |
1da177e4c Linux-2.6.12-rc2 |
31 |
|
d2df0484b lockd: Rename nlm... |
32 |
static struct hlist_head nlm_server_hosts[NLM_HOST_NRHASH]; |
8ea6ecc8b lockd: Create cli... |
33 |
static struct hlist_head nlm_client_hosts[NLM_HOST_NRHASH]; |
b11374688 lockd: define hos... |
34 |
|
b67bfe0d4 hlist: drop the n... |
35 |
#define for_each_host(host, chain, table) \ |
b11374688 lockd: define hos... |
36 37 |
for ((chain) = (table); \ (chain) < (table) + NLM_HOST_NRHASH; ++(chain)) \ |
b67bfe0d4 hlist: drop the n... |
38 |
hlist_for_each_entry((host), (chain), h_hash) |
b11374688 lockd: define hos... |
39 |
|
b67bfe0d4 hlist: drop the n... |
40 |
#define for_each_host_safe(host, next, chain, table) \ |
b11374688 lockd: define hos... |
41 42 |
for ((chain) = (table); \ (chain) < (table) + NLM_HOST_NRHASH; ++(chain)) \ |
b67bfe0d4 hlist: drop the n... |
43 |
hlist_for_each_entry_safe((host), (next), \ |
b11374688 lockd: define hos... |
44 |
(chain), h_hash) |
fcc072c78 lockd: Make nrhos... |
45 |
static unsigned long nrhosts; |
353ab6e97 [PATCH] sem2mutex... |
46 |
static DEFINE_MUTEX(nlm_host_mutex); |
1da177e4c Linux-2.6.12-rc2 |
47 |
|
27adaddc8 LockD: make garba... |
48 |
static void nlm_gc_hosts(struct net *net); |
1da177e4c Linux-2.6.12-rc2 |
49 |
|
7f1ed18bd NLM: Convert nlm_... |
50 51 |
struct nlm_lookup_host_info { const int server; /* search for server|client */ |
88541c848 lockd: Support no... |
52 53 |
const struct sockaddr *sap; /* address to search for */ const size_t salen; /* it's length */ |
7f1ed18bd NLM: Convert nlm_... |
54 55 56 57 |
const unsigned short protocol; /* transport to search for*/ const u32 version; /* NLM version to search for */ const char *hostname; /* remote's hostname */ const size_t hostname_len; /* it's length */ |
0cb2659b8 NLM: allow lockd ... |
58 |
const int noresvport; /* use non-priv port */ |
66697bfd6 LockD: make nlm h... |
59 |
struct net *net; /* network namespace to bind */ |
b422df915 lockd: Store the ... |
60 |
const struct cred *cred; |
7f1ed18bd NLM: Convert nlm_... |
61 |
}; |
ede2fea09 lockd: Support AF... |
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
/* * Hash function must work well on big- and little-endian platforms */ static unsigned int __nlm_hash32(const __be32 n) { unsigned int hash = (__force u32)n ^ ((__force u32)n >> 16); return hash ^ (hash >> 8); } static unsigned int __nlm_hash_addr4(const struct sockaddr *sap) { const struct sockaddr_in *sin = (struct sockaddr_in *)sap; return __nlm_hash32(sin->sin_addr.s_addr); } static unsigned int __nlm_hash_addr6(const struct sockaddr *sap) { const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; const struct in6_addr addr = sin6->sin6_addr; return __nlm_hash32(addr.s6_addr32[0]) ^ __nlm_hash32(addr.s6_addr32[1]) ^ __nlm_hash32(addr.s6_addr32[2]) ^ __nlm_hash32(addr.s6_addr32[3]); } static unsigned int nlm_hash_address(const struct sockaddr *sap) { unsigned int hash; switch (sap->sa_family) { case AF_INET: hash = __nlm_hash_addr4(sap); break; case AF_INET6: hash = __nlm_hash_addr6(sap); break; default: hash = 0; } return hash & (NLM_HOST_NRHASH - 1); } |
1da177e4c Linux-2.6.12-rc2 |
103 |
/* |
a7952f405 lockd: Add nlm_al... |
104 105 106 107 108 109 110 111 112 |
* Allocate and initialize an nlm_host. Common to both client and server. */ static struct nlm_host *nlm_alloc_host(struct nlm_lookup_host_info *ni, struct nsm_handle *nsm) { struct nlm_host *host = NULL; unsigned long now = jiffies; if (nsm != NULL) |
c751082ce lockd: convert ns... |
113 |
refcount_inc(&nsm->sm_count); |
a7952f405 lockd: Add nlm_al... |
114 115 |
else { host = NULL; |
0ad95472b lockd: create NSM... |
116 |
nsm = nsm_get_handle(ni->net, ni->sap, ni->salen, |
a7952f405 lockd: Add nlm_al... |
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
ni->hostname, ni->hostname_len); if (unlikely(nsm == NULL)) { dprintk("lockd: %s failed; no nsm handle ", __func__); goto out; } } host = kmalloc(sizeof(*host), GFP_KERNEL); if (unlikely(host == NULL)) { dprintk("lockd: %s failed; no memory ", __func__); nsm_release(nsm); goto out; } memcpy(nlm_addr(host), ni->sap, ni->salen); host->h_addrlen = ni->salen; rpc_set_port(nlm_addr(host), 0); host->h_srcaddrlen = 0; host->h_rpcclnt = NULL; host->h_name = nsm->sm_name; host->h_version = ni->version; host->h_proto = ni->protocol; host->h_reclaiming = 0; host->h_server = ni->server; host->h_noresvport = ni->noresvport; host->h_inuse = 0; init_waitqueue_head(&host->h_gracewait); init_rwsem(&host->h_rwsem); host->h_state = 0; host->h_nsmstate = 0; host->h_pidcount = 0; |
fee21fb58 lockd: convert nl... |
152 |
refcount_set(&host->h_count, 1); |
a7952f405 lockd: Add nlm_al... |
153 154 155 156 157 158 159 160 161 |
mutex_init(&host->h_mutex); host->h_nextrebind = now + NLM_HOST_REBIND; host->h_expires = now + NLM_HOST_EXPIRE; INIT_LIST_HEAD(&host->h_lockowners); spin_lock_init(&host->h_lock); INIT_LIST_HEAD(&host->h_granted); INIT_LIST_HEAD(&host->h_reclaim); host->h_nsmhandle = nsm; host->h_addrbuf = nsm->sm_addrbuf; |
66697bfd6 LockD: make nlm h... |
162 |
host->net = ni->net; |
b422df915 lockd: Store the ... |
163 |
host->h_cred = get_cred(ni->cred), |
0d0f4aab4 lockd: get rid of... |
164 |
strlcpy(host->nodename, utsname()->nodename, sizeof(host->nodename)); |
a7952f405 lockd: Add nlm_al... |
165 166 167 168 169 170 |
out: return host; } /* |
723bb5b50 lockd: Add nlm_de... |
171 172 173 |
* Destroy an nlm_host and free associated resources * * Caller must hold nlm_host_mutex. |
c53c1bb94 [PATCH] knfsd: lo... |
174 |
*/ |
723bb5b50 lockd: Add nlm_de... |
175 |
static void nlm_destroy_host_locked(struct nlm_host *host) |
c53c1bb94 [PATCH] knfsd: lo... |
176 177 |
{ struct rpc_clnt *clnt; |
caa4e76b6 LockD: manage use... |
178 |
struct lockd_net *ln = net_generic(host->net, lockd_net_id); |
c53c1bb94 [PATCH] knfsd: lo... |
179 |
|
723bb5b50 lockd: Add nlm_de... |
180 181 |
dprintk("lockd: destroy host %s ", host->h_name); |
723bb5b50 lockd: Add nlm_de... |
182 |
hlist_del_init(&host->h_hash); |
c53c1bb94 [PATCH] knfsd: lo... |
183 |
nsm_unmonitor(host); |
c8c23c423 NSM: Release nsmh... |
184 |
nsm_release(host->h_nsmhandle); |
c53c1bb94 [PATCH] knfsd: lo... |
185 |
|
34f52e359 SUNRPC: Convert r... |
186 187 188 |
clnt = host->h_rpcclnt; if (clnt != NULL) rpc_shutdown_client(clnt); |
b422df915 lockd: Store the ... |
189 |
put_cred(host->h_cred); |
c53c1bb94 [PATCH] knfsd: lo... |
190 |
kfree(host); |
723bb5b50 lockd: Add nlm_de... |
191 |
|
caa4e76b6 LockD: manage use... |
192 |
ln->nrhosts--; |
723bb5b50 lockd: Add nlm_de... |
193 |
nrhosts--; |
c53c1bb94 [PATCH] knfsd: lo... |
194 |
} |
d7d204403 lockd: Adjust nlm... |
195 196 197 198 199 200 201 |
/** * nlmclnt_lookup_host - Find an NLM host handle matching a remote server * @sap: network address of server * @salen: length of server address * @protocol: transport protocol to use * @version: NLM protocol version * @hostname: '\0'-terminated hostname of server |
0cb2659b8 NLM: allow lockd ... |
202 |
* @noresvport: 1 if non-privileged port should be used |
b422df915 lockd: Store the ... |
203 204 |
* @net: pointer to net namespace * @cred: pointer to cred |
d7d204403 lockd: Adjust nlm... |
205 206 207 208 209 |
* * Returns an nlm_host structure that matches the passed-in * [server address, transport protocol, NLM version, server hostname]. * If one doesn't already exist in the host cache, a new handle is * created and returned. |
c585646dd [PATCH] fs/lockd/... |
210 |
*/ |
d7d204403 lockd: Adjust nlm... |
211 212 213 |
struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap, const size_t salen, const unsigned short protocol, |
0cb2659b8 NLM: allow lockd ... |
214 215 |
const u32 version, const char *hostname, |
66697bfd6 LockD: make nlm h... |
216 |
int noresvport, |
b422df915 lockd: Store the ... |
217 218 |
struct net *net, const struct cred *cred) |
c585646dd [PATCH] fs/lockd/... |
219 |
{ |
7f1ed18bd NLM: Convert nlm_... |
220 221 |
struct nlm_lookup_host_info ni = { .server = 0, |
d7d204403 lockd: Adjust nlm... |
222 223 224 |
.sap = sap, .salen = salen, .protocol = protocol, |
7f1ed18bd NLM: Convert nlm_... |
225 226 |
.version = version, .hostname = hostname, |
d7d204403 lockd: Adjust nlm... |
227 |
.hostname_len = strlen(hostname), |
0cb2659b8 NLM: allow lockd ... |
228 |
.noresvport = noresvport, |
66697bfd6 LockD: make nlm h... |
229 |
.net = net, |
b422df915 lockd: Store the ... |
230 |
.cred = cred, |
7f1ed18bd NLM: Convert nlm_... |
231 |
}; |
8ea6ecc8b lockd: Create cli... |
232 |
struct hlist_head *chain; |
8ea6ecc8b lockd: Create cli... |
233 234 |
struct nlm_host *host; struct nsm_handle *nsm = NULL; |
caa4e76b6 LockD: manage use... |
235 |
struct lockd_net *ln = net_generic(net, lockd_net_id); |
c98451bdb NLM: fix source a... |
236 |
|
7f1ed18bd NLM: Convert nlm_... |
237 238 239 |
dprintk("lockd: %s(host='%s', vers=%u, proto=%s) ", __func__, (hostname ? hostname : "<none>"), version, |
d7d204403 lockd: Adjust nlm... |
240 |
(protocol == IPPROTO_UDP ? "udp" : "tcp")); |
7f1ed18bd NLM: Convert nlm_... |
241 |
|
8ea6ecc8b lockd: Create cli... |
242 243 244 |
mutex_lock(&nlm_host_mutex); chain = &nlm_client_hosts[nlm_hash_address(sap)]; |
b67bfe0d4 hlist: drop the n... |
245 |
hlist_for_each_entry(host, chain, h_hash) { |
66697bfd6 LockD: make nlm h... |
246 247 |
if (host->net != net) continue; |
8ea6ecc8b lockd: Create cli... |
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
if (!rpc_cmp_addr(nlm_addr(host), sap)) continue; /* Same address. Share an NSM handle if we already have one */ if (nsm == NULL) nsm = host->h_nsmhandle; if (host->h_proto != protocol) continue; if (host->h_version != version) continue; nlm_get_host(host); dprintk("lockd: %s found host %s (%s) ", __func__, host->h_name, host->h_addrbuf); goto out; } host = nlm_alloc_host(&ni, nsm); if (unlikely(host == NULL)) goto out; hlist_add_head(&host->h_hash, chain); |
caa4e76b6 LockD: manage use... |
272 |
ln->nrhosts++; |
8ea6ecc8b lockd: Create cli... |
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
nrhosts++; dprintk("lockd: %s created host %s (%s) ", __func__, host->h_name, host->h_addrbuf); out: mutex_unlock(&nlm_host_mutex); return host; } /** * nlmclnt_release_host - release client nlm_host * @host: nlm_host to release * */ void nlmclnt_release_host(struct nlm_host *host) { if (host == NULL) return; dprintk("lockd: release client host %s ", host->h_name); |
a2d30a54d lockd: Remove BUG... |
296 |
WARN_ON_ONCE(host->h_server); |
8ea6ecc8b lockd: Create cli... |
297 |
|
4a9be28c4 NFS: fix mount/um... |
298 |
if (refcount_dec_and_mutex_lock(&host->h_count, &nlm_host_mutex)) { |
a2d30a54d lockd: Remove BUG... |
299 300 301 |
WARN_ON_ONCE(!list_empty(&host->h_lockowners)); WARN_ON_ONCE(!list_empty(&host->h_granted)); WARN_ON_ONCE(!list_empty(&host->h_reclaim)); |
8ea6ecc8b lockd: Create cli... |
302 |
|
8ea6ecc8b lockd: Create cli... |
303 304 305 |
nlm_destroy_host_locked(host); mutex_unlock(&nlm_host_mutex); } |
c585646dd [PATCH] fs/lockd/... |
306 |
} |
6bfbe8af4 lockd: Adjust nlm... |
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
/** * nlmsvc_lookup_host - Find an NLM host handle matching a remote client * @rqstp: incoming NLM request * @hostname: name of client host * @hostname_len: length of client hostname * * Returns an nlm_host structure that matches the [client address, * transport protocol, NLM version, client hostname] of the passed-in * NLM request. If one doesn't already exist in the host cache, a * new handle is created and returned. * * Before possibly creating a new nlm_host, construct a sockaddr * for a specific source address in case the local system has * multiple network addresses. The family of the address in * rq_daddr is guaranteed to be the same as the family of the * address in rq_addr, so it's safe to use the same family for * the source address. |
c585646dd [PATCH] fs/lockd/... |
324 |
*/ |
6bfbe8af4 lockd: Adjust nlm... |
325 326 327 |
struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, const char *hostname, const size_t hostname_len) |
c585646dd [PATCH] fs/lockd/... |
328 |
{ |
67216b94d lockd: Clean up n... |
329 |
struct hlist_head *chain; |
67216b94d lockd: Clean up n... |
330 331 |
struct nlm_host *host = NULL; struct nsm_handle *nsm = NULL; |
849a1cf13 SUNRPC: Replace s... |
332 333 |
struct sockaddr *src_sap = svc_daddr(rqstp); size_t src_len = rqstp->rq_daddrlen; |
9695c7057 SUNRPC: service r... |
334 |
struct net *net = SVC_NET(rqstp); |
7f1ed18bd NLM: Convert nlm_... |
335 336 |
struct nlm_lookup_host_info ni = { .server = 1, |
88541c848 lockd: Support no... |
337 338 |
.sap = svc_addr(rqstp), .salen = rqstp->rq_addrlen, |
7f1ed18bd NLM: Convert nlm_... |
339 340 341 342 |
.protocol = rqstp->rq_prot, .version = rqstp->rq_vers, .hostname = hostname, .hostname_len = hostname_len, |
66697bfd6 LockD: make nlm h... |
343 |
.net = net, |
7f1ed18bd NLM: Convert nlm_... |
344 |
}; |
3cf7fb07e LockD: manage gar... |
345 |
struct lockd_net *ln = net_generic(net, lockd_net_id); |
7f1ed18bd NLM: Convert nlm_... |
346 |
|
93f38b6fa lockd: fix access... |
347 348 |
dprintk("lockd: %s(host='%.*s', vers=%u, proto=%s) ", __func__, |
7f1ed18bd NLM: Convert nlm_... |
349 350 |
(int)hostname_len, hostname, rqstp->rq_vers, (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp")); |
c98451bdb NLM: fix source a... |
351 |
|
67216b94d lockd: Clean up n... |
352 |
mutex_lock(&nlm_host_mutex); |
3cf7fb07e LockD: manage gar... |
353 |
if (time_after_eq(jiffies, ln->next_gc)) |
27adaddc8 LockD: make garba... |
354 |
nlm_gc_hosts(net); |
67216b94d lockd: Clean up n... |
355 |
|
d2df0484b lockd: Rename nlm... |
356 |
chain = &nlm_server_hosts[nlm_hash_address(ni.sap)]; |
b67bfe0d4 hlist: drop the n... |
357 |
hlist_for_each_entry(host, chain, h_hash) { |
66697bfd6 LockD: make nlm h... |
358 359 |
if (host->net != net) continue; |
67216b94d lockd: Clean up n... |
360 361 362 363 364 365 366 367 368 369 370 |
if (!rpc_cmp_addr(nlm_addr(host), ni.sap)) continue; /* Same address. Share an NSM handle if we already have one */ if (nsm == NULL) nsm = host->h_nsmhandle; if (host->h_proto != ni.protocol) continue; if (host->h_version != ni.version) continue; |
796918366 lockd: Remove src... |
371 |
if (!rpc_cmp_addr(nlm_srcaddr(host), src_sap)) |
67216b94d lockd: Clean up n... |
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 |
continue; /* Move to head of hash chain. */ hlist_del(&host->h_hash); hlist_add_head(&host->h_hash, chain); nlm_get_host(host); dprintk("lockd: %s found host %s (%s) ", __func__, host->h_name, host->h_addrbuf); goto out; } host = nlm_alloc_host(&ni, nsm); if (unlikely(host == NULL)) goto out; |
796918366 lockd: Remove src... |
388 389 |
memcpy(nlm_srcaddr(host), src_sap, src_len); host->h_srcaddrlen = src_len; |
67216b94d lockd: Clean up n... |
390 |
hlist_add_head(&host->h_hash, chain); |
caa4e76b6 LockD: manage use... |
391 |
ln->nrhosts++; |
67216b94d lockd: Clean up n... |
392 |
nrhosts++; |
535cb8f31 lockd: Fix server... |
393 |
refcount_inc(&host->h_count); |
67216b94d lockd: Clean up n... |
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
dprintk("lockd: %s created host %s (%s) ", __func__, host->h_name, host->h_addrbuf); out: mutex_unlock(&nlm_host_mutex); return host; } /** * nlmsvc_release_host - release server nlm_host * @host: nlm_host to release * * Host is destroyed later in nlm_gc_host(). */ void nlmsvc_release_host(struct nlm_host *host) { if (host == NULL) return; dprintk("lockd: release server host %s ", host->h_name); |
a2d30a54d lockd: Remove BUG... |
416 |
WARN_ON_ONCE(!host->h_server); |
fee21fb58 lockd: convert nl... |
417 |
refcount_dec(&host->h_count); |
c585646dd [PATCH] fs/lockd/... |
418 419 420 |
} /* |
1da177e4c Linux-2.6.12-rc2 |
421 422 423 424 425 426 |
* Create the NLM RPC client for an NLM peer */ struct rpc_clnt * nlm_bind_host(struct nlm_host *host) { struct rpc_clnt *clnt; |
1da177e4c Linux-2.6.12-rc2 |
427 |
|
1df40b609 NLM: Remove addre... |
428 429 430 |
dprintk("lockd: nlm_bind_host %s (%s) ", host->h_name, host->h_addrbuf); |
1da177e4c Linux-2.6.12-rc2 |
431 432 |
/* Lock host handle */ |
504679141 NLM: sem to mutex... |
433 |
mutex_lock(&host->h_mutex); |
1da177e4c Linux-2.6.12-rc2 |
434 435 436 |
/* If we've already created an RPC client, check whether * RPC rebind is required |
1da177e4c Linux-2.6.12-rc2 |
437 438 |
*/ if ((clnt = host->h_rpcclnt) != NULL) { |
0e1c02e4e lockd: don't use ... |
439 |
nlm_rebind_host(host); |
1da177e4c Linux-2.6.12-rc2 |
440 |
} else { |
21051ba62 NLM: Fix locking ... |
441 |
unsigned long increment = nlmsvc_timeout; |
e1ec78928 LOCKD: Convert to... |
442 443 444 445 446 447 448 |
struct rpc_timeout timeparms = { .to_initval = increment, .to_increment = increment, .to_maxval = increment * 6UL, .to_retries = 5U, }; struct rpc_create_args args = { |
66697bfd6 LockD: make nlm h... |
449 |
.net = host->net, |
e1ec78928 LOCKD: Convert to... |
450 |
.protocol = host->h_proto, |
b4ed58fd3 lockd: Use sockad... |
451 452 |
.address = nlm_addr(host), .addrsize = host->h_addrlen, |
e1ec78928 LOCKD: Convert to... |
453 454 455 456 457 |
.timeout = &timeparms, .servername = host->h_name, .program = &nlm_program, .version = host->h_version, .authflavor = RPC_AUTH_UNIX, |
90bd17c87 NLM: have server-... |
458 |
.flags = (RPC_CLNT_CREATE_NOPING | |
e6237b6fe NFSv4.1: Don't re... |
459 460 |
RPC_CLNT_CREATE_AUTOBIND | RPC_CLNT_CREATE_REUSEPORT), |
b422df915 lockd: Store the ... |
461 |
.cred = host->h_cred, |
e1ec78928 LOCKD: Convert to... |
462 |
}; |
90bd17c87 NLM: have server-... |
463 464 465 466 467 468 469 |
/* * lockd retries server side blocks automatically so we want * those to be soft RPC calls. Client side calls need to be * hard RPC tasks. */ if (!host->h_server) args.flags |= RPC_CLNT_CREATE_HARDRTRY; |
0cb2659b8 NLM: allow lockd ... |
470 471 |
if (host->h_noresvport) args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; |
8e35f8e7c NLM: Fix a regres... |
472 473 |
if (host->h_srcaddrlen) args.saddress = nlm_srcaddr(host); |
90bd17c87 NLM: have server-... |
474 |
|
e1ec78928 LOCKD: Convert to... |
475 476 477 478 479 480 481 482 |
clnt = rpc_create(&args); if (!IS_ERR(clnt)) host->h_rpcclnt = clnt; else { printk("lockd: couldn't create RPC handle for %s ", host->h_name); clnt = NULL; } |
1da177e4c Linux-2.6.12-rc2 |
483 |
} |
504679141 NLM: sem to mutex... |
484 |
mutex_unlock(&host->h_mutex); |
1da177e4c Linux-2.6.12-rc2 |
485 |
return clnt; |
1da177e4c Linux-2.6.12-rc2 |
486 |
} |
0e1c02e4e lockd: don't use ... |
487 488 489 490 491 492 493 |
/** * nlm_rebind_host - If needed, force a portmap lookup of the peer's lockd port * @host: NLM host handle for peer * * This is not needed when using a connection-oriented protocol, such as TCP. * The existing autobind mechanism is sufficient to force a rebind when * required, e.g. on connection state transitions. |
1da177e4c Linux-2.6.12-rc2 |
494 495 496 497 |
*/ void nlm_rebind_host(struct nlm_host *host) { |
0e1c02e4e lockd: don't use ... |
498 499 |
if (host->h_proto != IPPROTO_UDP) return; |
1da177e4c Linux-2.6.12-rc2 |
500 |
if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) { |
35f5a422c SUNRPC: new inter... |
501 |
rpc_force_rebind(host->h_rpcclnt); |
1da177e4c Linux-2.6.12-rc2 |
502 503 504 505 506 507 508 509 510 511 512 513 |
host->h_nextrebind = jiffies + NLM_HOST_REBIND; } } /* * Increment NLM host count */ struct nlm_host * nlm_get_host(struct nlm_host *host) { if (host) { dprintk("lockd: get host %s ", host->h_name); |
fee21fb58 lockd: convert nl... |
514 |
refcount_inc(&host->h_count); |
1da177e4c Linux-2.6.12-rc2 |
515 516 517 518 |
host->h_expires = jiffies + NLM_HOST_EXPIRE; } return host; } |
b10e30f65 lockd: reorganize... |
519 520 521 522 |
static struct nlm_host *next_host_state(struct hlist_head *cache, struct nsm_handle *nsm, const struct nlm_reboot *info) { |
80c30e8de NLM: Fix "kernel ... |
523 |
struct nlm_host *host; |
b10e30f65 lockd: reorganize... |
524 |
struct hlist_head *chain; |
b10e30f65 lockd: reorganize... |
525 526 |
mutex_lock(&nlm_host_mutex); |
b67bfe0d4 hlist: drop the n... |
527 |
for_each_host(host, chain, cache) { |
b10e30f65 lockd: reorganize... |
528 529 530 531 532 533 |
if (host->h_nsmhandle == nsm && host->h_nsmstate != info->state) { host->h_nsmstate = info->state; host->h_state++; nlm_get_host(host); |
80c30e8de NLM: Fix "kernel ... |
534 535 |
mutex_unlock(&nlm_host_mutex); return host; |
b10e30f65 lockd: reorganize... |
536 537 |
} } |
80c30e8de NLM: Fix "kernel ... |
538 |
|
b10e30f65 lockd: reorganize... |
539 |
mutex_unlock(&nlm_host_mutex); |
80c30e8de NLM: Fix "kernel ... |
540 |
return NULL; |
b10e30f65 lockd: reorganize... |
541 |
} |
7fefc9cb9 NLM: Change nlm_h... |
542 543 |
/** * nlm_host_rebooted - Release all resources held by rebooted host |
0ad95472b lockd: create NSM... |
544 |
* @net: network namespace |
7fefc9cb9 NLM: Change nlm_h... |
545 546 547 548 |
* @info: pointer to decoded results of NLM_SM_NOTIFY call * * We were notified that the specified host has rebooted. Release * all resources held by that peer. |
cf712c24d [PATCH] knfsd: co... |
549 |
*/ |
0ad95472b lockd: create NSM... |
550 |
void nlm_host_rebooted(const struct net *net, const struct nlm_reboot *info) |
cf712c24d [PATCH] knfsd: co... |
551 |
{ |
5c8dd29ca [PATCH] knfsd: lo... |
552 |
struct nsm_handle *nsm; |
0cea32761 [PATCH] knfsd: lo... |
553 |
struct nlm_host *host; |
cf712c24d [PATCH] knfsd: co... |
554 |
|
0ad95472b lockd: create NSM... |
555 |
nsm = nsm_reboot_lookup(net, info); |
8c7378fd2 NLM: Call nsm_reb... |
556 |
if (unlikely(nsm == NULL)) |
db4e4c9a9 [PATCH] knfsd: wh... |
557 |
return; |
5c8dd29ca [PATCH] knfsd: lo... |
558 559 560 561 562 563 |
/* Mark all hosts tied to this NSM state as having rebooted. * We run the loop repeatedly, because we drop the host table * lock for this. * To avoid processing a host several times, we match the nsmstate. */ |
d2df0484b lockd: Rename nlm... |
564 |
while ((host = next_host_state(nlm_server_hosts, nsm, info)) != NULL) { |
8ea6ecc8b lockd: Create cli... |
565 |
nlmsvc_free_host_resources(host); |
67216b94d lockd: Clean up n... |
566 |
nlmsvc_release_host(host); |
cf712c24d [PATCH] knfsd: co... |
567 |
} |
8ea6ecc8b lockd: Create cli... |
568 569 570 571 |
while ((host = next_host_state(nlm_client_hosts, nsm, info)) != NULL) { nlmclnt_recovery(host); nlmclnt_release_host(host); } |
cdd30fa16 lockd: release re... |
572 |
nsm_release(nsm); |
cf712c24d [PATCH] knfsd: co... |
573 |
} |
d5850ff9e Lockd: host compl... |
574 575 576 |
static void nlm_complain_hosts(struct net *net) { struct hlist_head *chain; |
d5850ff9e Lockd: host compl... |
577 578 579 580 581 582 583 |
struct nlm_host *host; if (net) { struct lockd_net *ln = net_generic(net, lockd_net_id); if (ln->nrhosts == 0) return; |
e919b0765 lockd: remove net... |
584 585 586 587 588 589 |
pr_warn("lockd: couldn't shutdown host module for net %x! ", net->ns.inum); dprintk("lockd: %lu hosts left in net %x: ", ln->nrhosts, net->ns.inum); |
d5850ff9e Lockd: host compl... |
590 591 592 593 594 595 596 597 |
} else { if (nrhosts == 0) return; printk(KERN_WARNING "lockd: couldn't shutdown host module! "); dprintk("lockd: %lu hosts left: ", nrhosts); } |
b67bfe0d4 hlist: drop the n... |
598 |
for_each_host(host, chain, nlm_server_hosts) { |
d5850ff9e Lockd: host compl... |
599 600 |
if (net && host->net != net) continue; |
e919b0765 lockd: remove net... |
601 602 |
dprintk(" %s (cnt %d use %d exp %ld net %x) ", |
fee21fb58 lockd: convert nl... |
603 |
host->h_name, refcount_read(&host->h_count), |
e919b0765 lockd: remove net... |
604 |
host->h_inuse, host->h_expires, host->net->ns.inum); |
d5850ff9e Lockd: host compl... |
605 606 |
} } |
1da177e4c Linux-2.6.12-rc2 |
607 |
void |
3b64739fb Lockd: shutdown N... |
608 |
nlm_shutdown_hosts_net(struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
609 |
{ |
0cea32761 [PATCH] knfsd: lo... |
610 |
struct hlist_head *chain; |
1da177e4c Linux-2.6.12-rc2 |
611 |
struct nlm_host *host; |
1da177e4c Linux-2.6.12-rc2 |
612 |
|
353ab6e97 [PATCH] sem2mutex... |
613 |
mutex_lock(&nlm_host_mutex); |
1da177e4c Linux-2.6.12-rc2 |
614 615 |
/* First, make all hosts eligible for gc */ |
e919b0765 lockd: remove net... |
616 617 618 |
dprintk("lockd: nuking all hosts in net %x... ", net ? net->ns.inum : 0); |
b67bfe0d4 hlist: drop the n... |
619 |
for_each_host(host, chain, nlm_server_hosts) { |
3b64739fb Lockd: shutdown N... |
620 621 |
if (net && host->net != net) continue; |
b11374688 lockd: define hos... |
622 623 624 625 |
host->h_expires = jiffies - 1; if (host->h_rpcclnt) { rpc_shutdown_client(host->h_rpcclnt); host->h_rpcclnt = NULL; |
d801b8616 NLM: tear down RP... |
626 |
} |
1da177e4c Linux-2.6.12-rc2 |
627 628 629 |
} /* Then, perform a garbage collection pass */ |
27adaddc8 LockD: make garba... |
630 |
nlm_gc_hosts(net); |
d5850ff9e Lockd: host compl... |
631 |
nlm_complain_hosts(net); |
9e137ed5a nlm_shutdown_host... |
632 |
mutex_unlock(&nlm_host_mutex); |
3b64739fb Lockd: shutdown N... |
633 634 635 636 637 638 639 640 641 |
} /* * Shut down the hosts module. * Note that this routine is called only at server shutdown time. */ void nlm_shutdown_hosts(void) { |
e2edaa98c Lockd: add more d... |
642 643 |
dprintk("lockd: shutting down host module "); |
3b64739fb Lockd: shutdown N... |
644 |
nlm_shutdown_hosts_net(NULL); |
1da177e4c Linux-2.6.12-rc2 |
645 646 647 648 649 650 651 652 |
} /* * Garbage collect any unused NLM hosts. * This GC combines reference counting for async operations with * mark & sweep for resources held by remote clients. */ static void |
27adaddc8 LockD: make garba... |
653 |
nlm_gc_hosts(struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
654 |
{ |
0cea32761 [PATCH] knfsd: lo... |
655 |
struct hlist_head *chain; |
b67bfe0d4 hlist: drop the n... |
656 |
struct hlist_node *next; |
0cea32761 [PATCH] knfsd: lo... |
657 |
struct nlm_host *host; |
1da177e4c Linux-2.6.12-rc2 |
658 |
|
e919b0765 lockd: remove net... |
659 660 661 |
dprintk("lockd: host garbage collection for net %x ", net ? net->ns.inum : 0); |
b67bfe0d4 hlist: drop the n... |
662 |
for_each_host(host, chain, nlm_server_hosts) { |
27adaddc8 LockD: make garba... |
663 664 |
if (net && host->net != net) continue; |
b11374688 lockd: define hos... |
665 |
host->h_inuse = 0; |
27adaddc8 LockD: make garba... |
666 |
} |
1da177e4c Linux-2.6.12-rc2 |
667 668 |
/* Mark all hosts that hold locks, blocks or shares */ |
b26411f85 LockD: mark host ... |
669 |
nlmsvc_mark_resources(net); |
1da177e4c Linux-2.6.12-rc2 |
670 |
|
b67bfe0d4 hlist: drop the n... |
671 |
for_each_host_safe(host, next, chain, nlm_server_hosts) { |
27adaddc8 LockD: make garba... |
672 673 |
if (net && host->net != net) continue; |
535cb8f31 lockd: Fix server... |
674 |
if (host->h_inuse || time_before(jiffies, host->h_expires)) { |
b11374688 lockd: define hos... |
675 |
dprintk("nlm_gc_hosts skipping %s " |
e919b0765 lockd: remove net... |
676 677 |
"(cnt %d use %d exp %ld net %x) ", |
fee21fb58 lockd: convert nl... |
678 |
host->h_name, refcount_read(&host->h_count), |
e919b0765 lockd: remove net... |
679 680 |
host->h_inuse, host->h_expires, host->net->ns.inum); |
b11374688 lockd: define hos... |
681 |
continue; |
1da177e4c Linux-2.6.12-rc2 |
682 |
} |
535cb8f31 lockd: Fix server... |
683 684 |
if (refcount_dec_if_one(&host->h_count)) nlm_destroy_host_locked(host); |
1da177e4c Linux-2.6.12-rc2 |
685 |
} |
3cf7fb07e LockD: manage gar... |
686 687 688 689 690 |
if (net) { struct lockd_net *ln = net_generic(net, lockd_net_id); ln->next_gc = jiffies + NLM_HOST_COLLECT; } |
1da177e4c Linux-2.6.12-rc2 |
691 |
} |