diff options
Diffstat (limited to 'fs/lockd/host.c')
-rw-r--r-- | fs/lockd/host.c | 86 |
1 files changed, 56 insertions, 30 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index be8f19d53183..3c4dc33c1bea 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
@@ -38,6 +38,17 @@ static struct nsm_handle *nsm_find(const struct sockaddr *sap, | |||
38 | const size_t hostname_len, | 38 | const size_t hostname_len, |
39 | const int create); | 39 | const int create); |
40 | 40 | ||
41 | struct nlm_lookup_host_info { | ||
42 | const int server; /* search for server|client */ | ||
43 | const struct sockaddr_in *sin; /* address to search for */ | ||
44 | const unsigned short protocol; /* transport to search for*/ | ||
45 | const u32 version; /* NLM version to search for */ | ||
46 | const char *hostname; /* remote's hostname */ | ||
47 | const size_t hostname_len; /* it's length */ | ||
48 | const struct sockaddr_in *src_sin; /* our address (optional) */ | ||
49 | const size_t src_len; /* it's length */ | ||
50 | }; | ||
51 | |||
41 | /* | 52 | /* |
42 | * Hash function must work well on big- and little-endian platforms | 53 | * Hash function must work well on big- and little-endian platforms |
43 | */ | 54 | */ |
@@ -121,23 +132,13 @@ static void nlm_display_address(const struct sockaddr *sap, | |||
121 | /* | 132 | /* |
122 | * Common host lookup routine for server & client | 133 | * Common host lookup routine for server & client |
123 | */ | 134 | */ |
124 | static struct nlm_host *nlm_lookup_host(int server, | 135 | static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni) |
125 | const struct sockaddr_in *sin, | ||
126 | int proto, u32 version, | ||
127 | const char *hostname, | ||
128 | unsigned int hostname_len, | ||
129 | const struct sockaddr_in *ssin) | ||
130 | { | 136 | { |
131 | struct hlist_head *chain; | 137 | struct hlist_head *chain; |
132 | struct hlist_node *pos; | 138 | struct hlist_node *pos; |
133 | struct nlm_host *host; | 139 | struct nlm_host *host; |
134 | struct nsm_handle *nsm = NULL; | 140 | struct nsm_handle *nsm = NULL; |
135 | 141 | ||
136 | dprintk("lockd: nlm_lookup_host(proto=%d, vers=%u," | ||
137 | " my role is %s, hostname=%.*s)\n", | ||
138 | proto, version, server ? "server" : "client", | ||
139 | hostname_len, hostname ? hostname : "<none>"); | ||
140 | |||
141 | mutex_lock(&nlm_host_mutex); | 142 | mutex_lock(&nlm_host_mutex); |
142 | 143 | ||
143 | if (time_after_eq(jiffies, next_gc)) | 144 | if (time_after_eq(jiffies, next_gc)) |
@@ -150,22 +151,23 @@ static struct nlm_host *nlm_lookup_host(int server, | |||
150 | * different NLM rpc_clients into one single nlm_host object. | 151 | * different NLM rpc_clients into one single nlm_host object. |
151 | * This would allow us to have one nlm_host per address. | 152 | * This would allow us to have one nlm_host per address. |
152 | */ | 153 | */ |
153 | chain = &nlm_hosts[nlm_hash_address((struct sockaddr *)sin)]; | 154 | chain = &nlm_hosts[nlm_hash_address((struct sockaddr *)ni->sin)]; |
154 | hlist_for_each_entry(host, pos, chain, h_hash) { | 155 | hlist_for_each_entry(host, pos, chain, h_hash) { |
155 | if (!nlm_cmp_addr(nlm_addr(host), (struct sockaddr *)sin)) | 156 | if (!nlm_cmp_addr(nlm_addr(host), (struct sockaddr *)ni->sin)) |
156 | continue; | 157 | continue; |
157 | 158 | ||
158 | /* See if we have an NSM handle for this client */ | 159 | /* See if we have an NSM handle for this client */ |
159 | if (!nsm) | 160 | if (!nsm) |
160 | nsm = host->h_nsmhandle; | 161 | nsm = host->h_nsmhandle; |
161 | 162 | ||
162 | if (host->h_proto != proto) | 163 | if (host->h_proto != ni->protocol) |
163 | continue; | 164 | continue; |
164 | if (host->h_version != version) | 165 | if (host->h_version != ni->version) |
165 | continue; | 166 | continue; |
166 | if (host->h_server != server) | 167 | if (host->h_server != ni->server) |
167 | continue; | 168 | continue; |
168 | if (!nlm_cmp_addr(nlm_srcaddr(host), (struct sockaddr *)ssin)) | 169 | if (!nlm_cmp_addr(nlm_srcaddr(host), |
170 | (struct sockaddr *)ni->src_sin)) | ||
169 | continue; | 171 | continue; |
170 | 172 | ||
171 | /* Move to head of hash chain. */ | 173 | /* Move to head of hash chain. */ |
@@ -186,8 +188,9 @@ static struct nlm_host *nlm_lookup_host(int server, | |||
186 | atomic_inc(&nsm->sm_count); | 188 | atomic_inc(&nsm->sm_count); |
187 | else { | 189 | else { |
188 | host = NULL; | 190 | host = NULL; |
189 | nsm = nsm_find((struct sockaddr *)sin, sizeof(*sin), | 191 | nsm = nsm_find((struct sockaddr *)ni->sin, |
190 | hostname, hostname_len, 1); | 192 | sizeof(struct sockaddr_in), |
193 | ni->hostname, ni->hostname_len, 1); | ||
191 | if (!nsm) { | 194 | if (!nsm) { |
192 | dprintk("lockd: nlm_lookup_host failed; " | 195 | dprintk("lockd: nlm_lookup_host failed; " |
193 | "no nsm handle\n"); | 196 | "no nsm handle\n"); |
@@ -202,12 +205,12 @@ static struct nlm_host *nlm_lookup_host(int server, | |||
202 | goto out; | 205 | goto out; |
203 | } | 206 | } |
204 | host->h_name = nsm->sm_name; | 207 | host->h_name = nsm->sm_name; |
205 | memcpy(nlm_addr(host), sin, sizeof(*sin)); | 208 | memcpy(nlm_addr(host), ni->sin, sizeof(struct sockaddr_in)); |
206 | host->h_addrlen = sizeof(*sin); | 209 | host->h_addrlen = sizeof(struct sockaddr_in); |
207 | nlm_clear_port(nlm_addr(host)); | 210 | nlm_clear_port(nlm_addr(host)); |
208 | memcpy(nlm_srcaddr(host), ssin, sizeof(*ssin)); | 211 | memcpy(nlm_srcaddr(host), ni->src_sin, sizeof(struct sockaddr_in)); |
209 | host->h_version = version; | 212 | host->h_version = ni->version; |
210 | host->h_proto = proto; | 213 | host->h_proto = ni->protocol; |
211 | host->h_rpcclnt = NULL; | 214 | host->h_rpcclnt = NULL; |
212 | mutex_init(&host->h_mutex); | 215 | mutex_init(&host->h_mutex); |
213 | host->h_nextrebind = jiffies + NLM_HOST_REBIND; | 216 | host->h_nextrebind = jiffies + NLM_HOST_REBIND; |
@@ -218,7 +221,7 @@ static struct nlm_host *nlm_lookup_host(int server, | |||
218 | host->h_state = 0; /* pseudo NSM state */ | 221 | host->h_state = 0; /* pseudo NSM state */ |
219 | host->h_nsmstate = 0; /* real NSM state */ | 222 | host->h_nsmstate = 0; /* real NSM state */ |
220 | host->h_nsmhandle = nsm; | 223 | host->h_nsmhandle = nsm; |
221 | host->h_server = server; | 224 | host->h_server = ni->server; |
222 | hlist_add_head(&host->h_hash, chain); | 225 | hlist_add_head(&host->h_hash, chain); |
223 | INIT_LIST_HEAD(&host->h_lockowners); | 226 | INIT_LIST_HEAD(&host->h_lockowners); |
224 | spin_lock_init(&host->h_lock); | 227 | spin_lock_init(&host->h_lock); |
@@ -273,9 +276,21 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr_in *sin, | |||
273 | const struct sockaddr_in source = { | 276 | const struct sockaddr_in source = { |
274 | .sin_family = AF_UNSPEC, | 277 | .sin_family = AF_UNSPEC, |
275 | }; | 278 | }; |
279 | struct nlm_lookup_host_info ni = { | ||
280 | .server = 0, | ||
281 | .sin = sin, | ||
282 | .protocol = proto, | ||
283 | .version = version, | ||
284 | .hostname = hostname, | ||
285 | .hostname_len = hostname_len, | ||
286 | .src_sin = &source, | ||
287 | }; | ||
276 | 288 | ||
277 | return nlm_lookup_host(0, sin, proto, version, | 289 | dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__, |
278 | hostname, hostname_len, &source); | 290 | (hostname ? hostname : "<none>"), version, |
291 | (proto == IPPROTO_UDP ? "udp" : "tcp")); | ||
292 | |||
293 | return nlm_lookup_host(&ni); | ||
279 | } | 294 | } |
280 | 295 | ||
281 | /* | 296 | /* |
@@ -289,10 +304,21 @@ nlmsvc_lookup_host(struct svc_rqst *rqstp, | |||
289 | .sin_family = AF_INET, | 304 | .sin_family = AF_INET, |
290 | .sin_addr = rqstp->rq_daddr.addr, | 305 | .sin_addr = rqstp->rq_daddr.addr, |
291 | }; | 306 | }; |
307 | struct nlm_lookup_host_info ni = { | ||
308 | .server = 1, | ||
309 | .sin = svc_addr_in(rqstp), | ||
310 | .protocol = rqstp->rq_prot, | ||
311 | .version = rqstp->rq_vers, | ||
312 | .hostname = hostname, | ||
313 | .hostname_len = hostname_len, | ||
314 | .src_sin = &source, | ||
315 | }; | ||
316 | |||
317 | dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, | ||
318 | (int)hostname_len, hostname, rqstp->rq_vers, | ||
319 | (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp")); | ||
292 | 320 | ||
293 | return nlm_lookup_host(1, svc_addr_in(rqstp), | 321 | return nlm_lookup_host(&ni); |
294 | rqstp->rq_prot, rqstp->rq_vers, | ||
295 | hostname, hostname_len, &source); | ||
296 | } | 322 | } |
297 | 323 | ||
298 | /* | 324 | /* |