diff options
Diffstat (limited to 'fs/lockd/host.c')
-rw-r--r-- | fs/lockd/host.c | 350 |
1 files changed, 257 insertions, 93 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index a17664c7eacc..9fd8889097b7 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
@@ -11,16 +11,17 @@ | |||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/in.h> | 13 | #include <linux/in.h> |
14 | #include <linux/in6.h> | ||
14 | #include <linux/sunrpc/clnt.h> | 15 | #include <linux/sunrpc/clnt.h> |
15 | #include <linux/sunrpc/svc.h> | 16 | #include <linux/sunrpc/svc.h> |
16 | #include <linux/lockd/lockd.h> | 17 | #include <linux/lockd/lockd.h> |
17 | #include <linux/lockd/sm_inter.h> | 18 | #include <linux/lockd/sm_inter.h> |
18 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
19 | 20 | ||
21 | #include <net/ipv6.h> | ||
20 | 22 | ||
21 | #define NLMDBG_FACILITY NLMDBG_HOSTCACHE | 23 | #define NLMDBG_FACILITY NLMDBG_HOSTCACHE |
22 | #define NLM_HOST_NRHASH 32 | 24 | #define NLM_HOST_NRHASH 32 |
23 | #define NLM_ADDRHASH(addr) (ntohl(addr) & (NLM_HOST_NRHASH-1)) | ||
24 | #define NLM_HOST_REBIND (60 * HZ) | 25 | #define NLM_HOST_REBIND (60 * HZ) |
25 | #define NLM_HOST_EXPIRE (300 * HZ) | 26 | #define NLM_HOST_EXPIRE (300 * HZ) |
26 | #define NLM_HOST_COLLECT (120 * HZ) | 27 | #define NLM_HOST_COLLECT (120 * HZ) |
@@ -30,42 +31,115 @@ static unsigned long next_gc; | |||
30 | static int nrhosts; | 31 | static int nrhosts; |
31 | static DEFINE_MUTEX(nlm_host_mutex); | 32 | static DEFINE_MUTEX(nlm_host_mutex); |
32 | 33 | ||
33 | |||
34 | static void nlm_gc_hosts(void); | 34 | static void nlm_gc_hosts(void); |
35 | static struct nsm_handle * __nsm_find(const struct sockaddr_in *, | 35 | static struct nsm_handle *nsm_find(const struct sockaddr *sap, |
36 | const char *, unsigned int, int); | 36 | const size_t salen, |
37 | static struct nsm_handle * nsm_find(const struct sockaddr_in *sin, | 37 | const char *hostname, |
38 | const char *hostname, | 38 | const size_t hostname_len, |
39 | unsigned int hostname_len); | 39 | const int create); |
40 | |||
41 | struct nlm_lookup_host_info { | ||
42 | const int server; /* search for server|client */ | ||
43 | const struct sockaddr *sap; /* address to search for */ | ||
44 | const size_t salen; /* it's length */ | ||
45 | const unsigned short protocol; /* transport to search for*/ | ||
46 | const u32 version; /* NLM version to search for */ | ||
47 | const char *hostname; /* remote's hostname */ | ||
48 | const size_t hostname_len; /* it's length */ | ||
49 | const struct sockaddr *src_sap; /* our address (optional) */ | ||
50 | const size_t src_len; /* it's length */ | ||
51 | }; | ||
52 | |||
53 | /* | ||
54 | * Hash function must work well on big- and little-endian platforms | ||
55 | */ | ||
56 | static unsigned int __nlm_hash32(const __be32 n) | ||
57 | { | ||
58 | unsigned int hash = (__force u32)n ^ ((__force u32)n >> 16); | ||
59 | return hash ^ (hash >> 8); | ||
60 | } | ||
61 | |||
62 | static unsigned int __nlm_hash_addr4(const struct sockaddr *sap) | ||
63 | { | ||
64 | const struct sockaddr_in *sin = (struct sockaddr_in *)sap; | ||
65 | return __nlm_hash32(sin->sin_addr.s_addr); | ||
66 | } | ||
67 | |||
68 | static unsigned int __nlm_hash_addr6(const struct sockaddr *sap) | ||
69 | { | ||
70 | const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; | ||
71 | const struct in6_addr addr = sin6->sin6_addr; | ||
72 | return __nlm_hash32(addr.s6_addr32[0]) ^ | ||
73 | __nlm_hash32(addr.s6_addr32[1]) ^ | ||
74 | __nlm_hash32(addr.s6_addr32[2]) ^ | ||
75 | __nlm_hash32(addr.s6_addr32[3]); | ||
76 | } | ||
77 | |||
78 | static unsigned int nlm_hash_address(const struct sockaddr *sap) | ||
79 | { | ||
80 | unsigned int hash; | ||
81 | |||
82 | switch (sap->sa_family) { | ||
83 | case AF_INET: | ||
84 | hash = __nlm_hash_addr4(sap); | ||
85 | break; | ||
86 | case AF_INET6: | ||
87 | hash = __nlm_hash_addr6(sap); | ||
88 | break; | ||
89 | default: | ||
90 | hash = 0; | ||
91 | } | ||
92 | return hash & (NLM_HOST_NRHASH - 1); | ||
93 | } | ||
94 | |||
95 | static void nlm_clear_port(struct sockaddr *sap) | ||
96 | { | ||
97 | switch (sap->sa_family) { | ||
98 | case AF_INET: | ||
99 | ((struct sockaddr_in *)sap)->sin_port = 0; | ||
100 | break; | ||
101 | case AF_INET6: | ||
102 | ((struct sockaddr_in6 *)sap)->sin6_port = 0; | ||
103 | break; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static void nlm_display_address(const struct sockaddr *sap, | ||
108 | char *buf, const size_t len) | ||
109 | { | ||
110 | const struct sockaddr_in *sin = (struct sockaddr_in *)sap; | ||
111 | const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; | ||
112 | |||
113 | switch (sap->sa_family) { | ||
114 | case AF_UNSPEC: | ||
115 | snprintf(buf, len, "unspecified"); | ||
116 | break; | ||
117 | case AF_INET: | ||
118 | snprintf(buf, len, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr)); | ||
119 | break; | ||
120 | case AF_INET6: | ||
121 | if (ipv6_addr_v4mapped(&sin6->sin6_addr)) | ||
122 | snprintf(buf, len, NIPQUAD_FMT, | ||
123 | NIPQUAD(sin6->sin6_addr.s6_addr32[3])); | ||
124 | else | ||
125 | snprintf(buf, len, NIP6_FMT, NIP6(sin6->sin6_addr)); | ||
126 | break; | ||
127 | default: | ||
128 | snprintf(buf, len, "unsupported address family"); | ||
129 | break; | ||
130 | } | ||
131 | } | ||
40 | 132 | ||
41 | /* | 133 | /* |
42 | * Common host lookup routine for server & client | 134 | * Common host lookup routine for server & client |
43 | */ | 135 | */ |
44 | static struct nlm_host *nlm_lookup_host(int server, | 136 | static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni) |
45 | const struct sockaddr_in *sin, | ||
46 | int proto, u32 version, | ||
47 | const char *hostname, | ||
48 | unsigned int hostname_len, | ||
49 | const struct sockaddr_in *ssin) | ||
50 | { | 137 | { |
51 | struct hlist_head *chain; | 138 | struct hlist_head *chain; |
52 | struct hlist_node *pos; | 139 | struct hlist_node *pos; |
53 | struct nlm_host *host; | 140 | struct nlm_host *host; |
54 | struct nsm_handle *nsm = NULL; | 141 | struct nsm_handle *nsm = NULL; |
55 | int hash; | ||
56 | |||
57 | dprintk("lockd: nlm_lookup_host("NIPQUAD_FMT"->"NIPQUAD_FMT | ||
58 | ", p=%d, v=%u, my role=%s, name=%.*s)\n", | ||
59 | NIPQUAD(ssin->sin_addr.s_addr), | ||
60 | NIPQUAD(sin->sin_addr.s_addr), proto, version, | ||
61 | server? "server" : "client", | ||
62 | hostname_len, | ||
63 | hostname? hostname : "<none>"); | ||
64 | 142 | ||
65 | |||
66 | hash = NLM_ADDRHASH(sin->sin_addr.s_addr); | ||
67 | |||
68 | /* Lock hash table */ | ||
69 | mutex_lock(&nlm_host_mutex); | 143 | mutex_lock(&nlm_host_mutex); |
70 | 144 | ||
71 | if (time_after_eq(jiffies, next_gc)) | 145 | if (time_after_eq(jiffies, next_gc)) |
@@ -78,22 +152,22 @@ static struct nlm_host *nlm_lookup_host(int server, | |||
78 | * different NLM rpc_clients into one single nlm_host object. | 152 | * different NLM rpc_clients into one single nlm_host object. |
79 | * This would allow us to have one nlm_host per address. | 153 | * This would allow us to have one nlm_host per address. |
80 | */ | 154 | */ |
81 | chain = &nlm_hosts[hash]; | 155 | chain = &nlm_hosts[nlm_hash_address(ni->sap)]; |
82 | hlist_for_each_entry(host, pos, chain, h_hash) { | 156 | hlist_for_each_entry(host, pos, chain, h_hash) { |
83 | if (!nlm_cmp_addr(&host->h_addr, sin)) | 157 | if (!nlm_cmp_addr(nlm_addr(host), ni->sap)) |
84 | continue; | 158 | continue; |
85 | 159 | ||
86 | /* See if we have an NSM handle for this client */ | 160 | /* See if we have an NSM handle for this client */ |
87 | if (!nsm) | 161 | if (!nsm) |
88 | nsm = host->h_nsmhandle; | 162 | nsm = host->h_nsmhandle; |
89 | 163 | ||
90 | if (host->h_proto != proto) | 164 | if (host->h_proto != ni->protocol) |
91 | continue; | 165 | continue; |
92 | if (host->h_version != version) | 166 | if (host->h_version != ni->version) |
93 | continue; | 167 | continue; |
94 | if (host->h_server != server) | 168 | if (host->h_server != ni->server) |
95 | continue; | 169 | continue; |
96 | if (!nlm_cmp_addr(&host->h_saddr, ssin)) | 170 | if (!nlm_cmp_addr(nlm_srcaddr(host), ni->src_sap)) |
97 | continue; | 171 | continue; |
98 | 172 | ||
99 | /* Move to head of hash chain. */ | 173 | /* Move to head of hash chain. */ |
@@ -101,30 +175,41 @@ static struct nlm_host *nlm_lookup_host(int server, | |||
101 | hlist_add_head(&host->h_hash, chain); | 175 | hlist_add_head(&host->h_hash, chain); |
102 | 176 | ||
103 | nlm_get_host(host); | 177 | nlm_get_host(host); |
178 | dprintk("lockd: nlm_lookup_host found host %s (%s)\n", | ||
179 | host->h_name, host->h_addrbuf); | ||
104 | goto out; | 180 | goto out; |
105 | } | 181 | } |
106 | if (nsm) | ||
107 | atomic_inc(&nsm->sm_count); | ||
108 | |||
109 | host = NULL; | ||
110 | 182 | ||
111 | /* Sadly, the host isn't in our hash table yet. See if | 183 | /* |
112 | * we have an NSM handle for it. If not, create one. | 184 | * The host wasn't in our hash table. If we don't |
185 | * have an NSM handle for it yet, create one. | ||
113 | */ | 186 | */ |
114 | if (!nsm && !(nsm = nsm_find(sin, hostname, hostname_len))) | 187 | if (nsm) |
115 | goto out; | 188 | atomic_inc(&nsm->sm_count); |
189 | else { | ||
190 | host = NULL; | ||
191 | nsm = nsm_find(ni->sap, ni->salen, | ||
192 | ni->hostname, ni->hostname_len, 1); | ||
193 | if (!nsm) { | ||
194 | dprintk("lockd: nlm_lookup_host failed; " | ||
195 | "no nsm handle\n"); | ||
196 | goto out; | ||
197 | } | ||
198 | } | ||
116 | 199 | ||
117 | host = kzalloc(sizeof(*host), GFP_KERNEL); | 200 | host = kzalloc(sizeof(*host), GFP_KERNEL); |
118 | if (!host) { | 201 | if (!host) { |
119 | nsm_release(nsm); | 202 | nsm_release(nsm); |
203 | dprintk("lockd: nlm_lookup_host failed; no memory\n"); | ||
120 | goto out; | 204 | goto out; |
121 | } | 205 | } |
122 | host->h_name = nsm->sm_name; | 206 | host->h_name = nsm->sm_name; |
123 | host->h_addr = *sin; | 207 | memcpy(nlm_addr(host), ni->sap, ni->salen); |
124 | host->h_addr.sin_port = 0; /* ouch! */ | 208 | host->h_addrlen = ni->salen; |
125 | host->h_saddr = *ssin; | 209 | nlm_clear_port(nlm_addr(host)); |
126 | host->h_version = version; | 210 | memcpy(nlm_srcaddr(host), ni->src_sap, ni->src_len); |
127 | host->h_proto = proto; | 211 | host->h_version = ni->version; |
212 | host->h_proto = ni->protocol; | ||
128 | host->h_rpcclnt = NULL; | 213 | host->h_rpcclnt = NULL; |
129 | mutex_init(&host->h_mutex); | 214 | mutex_init(&host->h_mutex); |
130 | host->h_nextrebind = jiffies + NLM_HOST_REBIND; | 215 | host->h_nextrebind = jiffies + NLM_HOST_REBIND; |
@@ -135,7 +220,7 @@ static struct nlm_host *nlm_lookup_host(int server, | |||
135 | host->h_state = 0; /* pseudo NSM state */ | 220 | host->h_state = 0; /* pseudo NSM state */ |
136 | host->h_nsmstate = 0; /* real NSM state */ | 221 | host->h_nsmstate = 0; /* real NSM state */ |
137 | host->h_nsmhandle = nsm; | 222 | host->h_nsmhandle = nsm; |
138 | host->h_server = server; | 223 | host->h_server = ni->server; |
139 | hlist_add_head(&host->h_hash, chain); | 224 | hlist_add_head(&host->h_hash, chain); |
140 | INIT_LIST_HEAD(&host->h_lockowners); | 225 | INIT_LIST_HEAD(&host->h_lockowners); |
141 | spin_lock_init(&host->h_lock); | 226 | spin_lock_init(&host->h_lock); |
@@ -143,6 +228,15 @@ static struct nlm_host *nlm_lookup_host(int server, | |||
143 | INIT_LIST_HEAD(&host->h_reclaim); | 228 | INIT_LIST_HEAD(&host->h_reclaim); |
144 | 229 | ||
145 | nrhosts++; | 230 | nrhosts++; |
231 | |||
232 | nlm_display_address((struct sockaddr *)&host->h_addr, | ||
233 | host->h_addrbuf, sizeof(host->h_addrbuf)); | ||
234 | nlm_display_address((struct sockaddr *)&host->h_srcaddr, | ||
235 | host->h_srcaddrbuf, sizeof(host->h_srcaddrbuf)); | ||
236 | |||
237 | dprintk("lockd: nlm_lookup_host created host %s\n", | ||
238 | host->h_name); | ||
239 | |||
146 | out: | 240 | out: |
147 | mutex_unlock(&nlm_host_mutex); | 241 | mutex_unlock(&nlm_host_mutex); |
148 | return host; | 242 | return host; |
@@ -170,33 +264,103 @@ nlm_destroy_host(struct nlm_host *host) | |||
170 | kfree(host); | 264 | kfree(host); |
171 | } | 265 | } |
172 | 266 | ||
173 | /* | 267 | /** |
174 | * Find an NLM server handle in the cache. If there is none, create it. | 268 | * nlmclnt_lookup_host - Find an NLM host handle matching a remote server |
269 | * @sap: network address of server | ||
270 | * @salen: length of server address | ||
271 | * @protocol: transport protocol to use | ||
272 | * @version: NLM protocol version | ||
273 | * @hostname: '\0'-terminated hostname of server | ||
274 | * | ||
275 | * Returns an nlm_host structure that matches the passed-in | ||
276 | * [server address, transport protocol, NLM version, server hostname]. | ||
277 | * If one doesn't already exist in the host cache, a new handle is | ||
278 | * created and returned. | ||
175 | */ | 279 | */ |
176 | struct nlm_host *nlmclnt_lookup_host(const struct sockaddr_in *sin, | 280 | struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap, |
177 | int proto, u32 version, | 281 | const size_t salen, |
178 | const char *hostname, | 282 | const unsigned short protocol, |
179 | unsigned int hostname_len) | 283 | const u32 version, const char *hostname) |
180 | { | 284 | { |
181 | struct sockaddr_in ssin = {0}; | 285 | const struct sockaddr source = { |
182 | 286 | .sa_family = AF_UNSPEC, | |
183 | return nlm_lookup_host(0, sin, proto, version, | 287 | }; |
184 | hostname, hostname_len, &ssin); | 288 | struct nlm_lookup_host_info ni = { |
289 | .server = 0, | ||
290 | .sap = sap, | ||
291 | .salen = salen, | ||
292 | .protocol = protocol, | ||
293 | .version = version, | ||
294 | .hostname = hostname, | ||
295 | .hostname_len = strlen(hostname), | ||
296 | .src_sap = &source, | ||
297 | .src_len = sizeof(source), | ||
298 | }; | ||
299 | |||
300 | dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__, | ||
301 | (hostname ? hostname : "<none>"), version, | ||
302 | (protocol == IPPROTO_UDP ? "udp" : "tcp")); | ||
303 | |||
304 | return nlm_lookup_host(&ni); | ||
185 | } | 305 | } |
186 | 306 | ||
187 | /* | 307 | /** |
188 | * Find an NLM client handle in the cache. If there is none, create it. | 308 | * nlmsvc_lookup_host - Find an NLM host handle matching a remote client |
309 | * @rqstp: incoming NLM request | ||
310 | * @hostname: name of client host | ||
311 | * @hostname_len: length of client hostname | ||
312 | * | ||
313 | * Returns an nlm_host structure that matches the [client address, | ||
314 | * transport protocol, NLM version, client hostname] of the passed-in | ||
315 | * NLM request. If one doesn't already exist in the host cache, a | ||
316 | * new handle is created and returned. | ||
317 | * | ||
318 | * Before possibly creating a new nlm_host, construct a sockaddr | ||
319 | * for a specific source address in case the local system has | ||
320 | * multiple network addresses. The family of the address in | ||
321 | * rq_daddr is guaranteed to be the same as the family of the | ||
322 | * address in rq_addr, so it's safe to use the same family for | ||
323 | * the source address. | ||
189 | */ | 324 | */ |
190 | struct nlm_host * | 325 | struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, |
191 | nlmsvc_lookup_host(struct svc_rqst *rqstp, | 326 | const char *hostname, |
192 | const char *hostname, unsigned int hostname_len) | 327 | const size_t hostname_len) |
193 | { | 328 | { |
194 | struct sockaddr_in ssin = {0}; | 329 | struct sockaddr_in sin = { |
330 | .sin_family = AF_INET, | ||
331 | }; | ||
332 | struct sockaddr_in6 sin6 = { | ||
333 | .sin6_family = AF_INET6, | ||
334 | }; | ||
335 | struct nlm_lookup_host_info ni = { | ||
336 | .server = 1, | ||
337 | .sap = svc_addr(rqstp), | ||
338 | .salen = rqstp->rq_addrlen, | ||
339 | .protocol = rqstp->rq_prot, | ||
340 | .version = rqstp->rq_vers, | ||
341 | .hostname = hostname, | ||
342 | .hostname_len = hostname_len, | ||
343 | .src_len = rqstp->rq_addrlen, | ||
344 | }; | ||
345 | |||
346 | dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, | ||
347 | (int)hostname_len, hostname, rqstp->rq_vers, | ||
348 | (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp")); | ||
349 | |||
350 | switch (ni.sap->sa_family) { | ||
351 | case AF_INET: | ||
352 | sin.sin_addr.s_addr = rqstp->rq_daddr.addr.s_addr; | ||
353 | ni.src_sap = (struct sockaddr *)&sin; | ||
354 | break; | ||
355 | case AF_INET6: | ||
356 | ipv6_addr_copy(&sin6.sin6_addr, &rqstp->rq_daddr.addr6); | ||
357 | ni.src_sap = (struct sockaddr *)&sin6; | ||
358 | break; | ||
359 | default: | ||
360 | return NULL; | ||
361 | } | ||
195 | 362 | ||
196 | ssin.sin_addr = rqstp->rq_daddr.addr; | 363 | return nlm_lookup_host(&ni); |
197 | return nlm_lookup_host(1, svc_addr_in(rqstp), | ||
198 | rqstp->rq_prot, rqstp->rq_vers, | ||
199 | hostname, hostname_len, &ssin); | ||
200 | } | 364 | } |
201 | 365 | ||
202 | /* | 366 | /* |
@@ -207,9 +371,8 @@ nlm_bind_host(struct nlm_host *host) | |||
207 | { | 371 | { |
208 | struct rpc_clnt *clnt; | 372 | struct rpc_clnt *clnt; |
209 | 373 | ||
210 | dprintk("lockd: nlm_bind_host("NIPQUAD_FMT"->"NIPQUAD_FMT")\n", | 374 | dprintk("lockd: nlm_bind_host %s (%s), my addr=%s\n", |
211 | NIPQUAD(host->h_saddr.sin_addr), | 375 | host->h_name, host->h_addrbuf, host->h_srcaddrbuf); |
212 | NIPQUAD(host->h_addr.sin_addr)); | ||
213 | 376 | ||
214 | /* Lock host handle */ | 377 | /* Lock host handle */ |
215 | mutex_lock(&host->h_mutex); | 378 | mutex_lock(&host->h_mutex); |
@@ -221,7 +384,7 @@ nlm_bind_host(struct nlm_host *host) | |||
221 | if (time_after_eq(jiffies, host->h_nextrebind)) { | 384 | if (time_after_eq(jiffies, host->h_nextrebind)) { |
222 | rpc_force_rebind(clnt); | 385 | rpc_force_rebind(clnt); |
223 | host->h_nextrebind = jiffies + NLM_HOST_REBIND; | 386 | host->h_nextrebind = jiffies + NLM_HOST_REBIND; |
224 | dprintk("lockd: next rebind in %ld jiffies\n", | 387 | dprintk("lockd: next rebind in %lu jiffies\n", |
225 | host->h_nextrebind - jiffies); | 388 | host->h_nextrebind - jiffies); |
226 | } | 389 | } |
227 | } else { | 390 | } else { |
@@ -234,9 +397,9 @@ nlm_bind_host(struct nlm_host *host) | |||
234 | }; | 397 | }; |
235 | struct rpc_create_args args = { | 398 | struct rpc_create_args args = { |
236 | .protocol = host->h_proto, | 399 | .protocol = host->h_proto, |
237 | .address = (struct sockaddr *)&host->h_addr, | 400 | .address = nlm_addr(host), |
238 | .addrsize = sizeof(host->h_addr), | 401 | .addrsize = host->h_addrlen, |
239 | .saddress = (struct sockaddr *)&host->h_saddr, | 402 | .saddress = nlm_srcaddr(host), |
240 | .timeout = &timeparms, | 403 | .timeout = &timeparms, |
241 | .servername = host->h_name, | 404 | .servername = host->h_name, |
242 | .program = &nlm_program, | 405 | .program = &nlm_program, |
@@ -324,12 +487,16 @@ void nlm_host_rebooted(const struct sockaddr_in *sin, | |||
324 | struct nsm_handle *nsm; | 487 | struct nsm_handle *nsm; |
325 | struct nlm_host *host; | 488 | struct nlm_host *host; |
326 | 489 | ||
327 | dprintk("lockd: nlm_host_rebooted(%s, %u.%u.%u.%u)\n", | 490 | nsm = nsm_find((struct sockaddr *)sin, sizeof(*sin), |
328 | hostname, NIPQUAD(sin->sin_addr)); | 491 | hostname, hostname_len, 0); |
329 | 492 | if (nsm == NULL) { | |
330 | /* Find the NSM handle for this peer */ | 493 | dprintk("lockd: never saw rebooted peer '%.*s' before\n", |
331 | if (!(nsm = __nsm_find(sin, hostname, hostname_len, 0))) | 494 | hostname_len, hostname); |
332 | return; | 495 | return; |
496 | } | ||
497 | |||
498 | dprintk("lockd: nlm_host_rebooted(%.*s, %s)\n", | ||
499 | hostname_len, hostname, nsm->sm_addrbuf); | ||
333 | 500 | ||
334 | /* When reclaiming locks on this peer, make sure that | 501 | /* When reclaiming locks on this peer, make sure that |
335 | * we set up a new notification */ | 502 | * we set up a new notification */ |
@@ -461,22 +628,23 @@ nlm_gc_hosts(void) | |||
461 | static LIST_HEAD(nsm_handles); | 628 | static LIST_HEAD(nsm_handles); |
462 | static DEFINE_SPINLOCK(nsm_lock); | 629 | static DEFINE_SPINLOCK(nsm_lock); |
463 | 630 | ||
464 | static struct nsm_handle * | 631 | static struct nsm_handle *nsm_find(const struct sockaddr *sap, |
465 | __nsm_find(const struct sockaddr_in *sin, | 632 | const size_t salen, |
466 | const char *hostname, unsigned int hostname_len, | 633 | const char *hostname, |
467 | int create) | 634 | const size_t hostname_len, |
635 | const int create) | ||
468 | { | 636 | { |
469 | struct nsm_handle *nsm = NULL; | 637 | struct nsm_handle *nsm = NULL; |
470 | struct nsm_handle *pos; | 638 | struct nsm_handle *pos; |
471 | 639 | ||
472 | if (!sin) | 640 | if (!sap) |
473 | return NULL; | 641 | return NULL; |
474 | 642 | ||
475 | if (hostname && memchr(hostname, '/', hostname_len) != NULL) { | 643 | if (hostname && memchr(hostname, '/', hostname_len) != NULL) { |
476 | if (printk_ratelimit()) { | 644 | if (printk_ratelimit()) { |
477 | printk(KERN_WARNING "Invalid hostname \"%.*s\" " | 645 | printk(KERN_WARNING "Invalid hostname \"%.*s\" " |
478 | "in NFS lock request\n", | 646 | "in NFS lock request\n", |
479 | hostname_len, hostname); | 647 | (int)hostname_len, hostname); |
480 | } | 648 | } |
481 | return NULL; | 649 | return NULL; |
482 | } | 650 | } |
@@ -489,7 +657,7 @@ retry: | |||
489 | if (strlen(pos->sm_name) != hostname_len | 657 | if (strlen(pos->sm_name) != hostname_len |
490 | || memcmp(pos->sm_name, hostname, hostname_len)) | 658 | || memcmp(pos->sm_name, hostname, hostname_len)) |
491 | continue; | 659 | continue; |
492 | } else if (!nlm_cmp_addr(&pos->sm_addr, sin)) | 660 | } else if (!nlm_cmp_addr(nsm_addr(pos), sap)) |
493 | continue; | 661 | continue; |
494 | atomic_inc(&pos->sm_count); | 662 | atomic_inc(&pos->sm_count); |
495 | kfree(nsm); | 663 | kfree(nsm); |
@@ -509,10 +677,13 @@ retry: | |||
509 | if (nsm == NULL) | 677 | if (nsm == NULL) |
510 | return NULL; | 678 | return NULL; |
511 | 679 | ||
512 | nsm->sm_addr = *sin; | 680 | memcpy(nsm_addr(nsm), sap, salen); |
681 | nsm->sm_addrlen = salen; | ||
513 | nsm->sm_name = (char *) (nsm + 1); | 682 | nsm->sm_name = (char *) (nsm + 1); |
514 | memcpy(nsm->sm_name, hostname, hostname_len); | 683 | memcpy(nsm->sm_name, hostname, hostname_len); |
515 | nsm->sm_name[hostname_len] = '\0'; | 684 | nsm->sm_name[hostname_len] = '\0'; |
685 | nlm_display_address((struct sockaddr *)&nsm->sm_addr, | ||
686 | nsm->sm_addrbuf, sizeof(nsm->sm_addrbuf)); | ||
516 | atomic_set(&nsm->sm_count, 1); | 687 | atomic_set(&nsm->sm_count, 1); |
517 | goto retry; | 688 | goto retry; |
518 | 689 | ||
@@ -521,13 +692,6 @@ found: | |||
521 | return nsm; | 692 | return nsm; |
522 | } | 693 | } |
523 | 694 | ||
524 | static struct nsm_handle * | ||
525 | nsm_find(const struct sockaddr_in *sin, const char *hostname, | ||
526 | unsigned int hostname_len) | ||
527 | { | ||
528 | return __nsm_find(sin, hostname, hostname_len, 1); | ||
529 | } | ||
530 | |||
531 | /* | 695 | /* |
532 | * Release an NSM handle | 696 | * Release an NSM handle |
533 | */ | 697 | */ |