diff options
author | Olaf Kirch <okir@suse.de> | 2006-10-04 05:15:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 10:55:17 -0400 |
commit | 5c8dd29ca7fc7483690cef4306549742d534f2a2 (patch) | |
tree | edf51e354535448ea6b57a59358d9f28c556684c | |
parent | f0737a39a64a9df32bb045c54e1cdf6cecdcbdd7 (diff) |
[PATCH] knfsd: lockd: Make nlm_host_rebooted use the nsm_handle
This patch makes the SM_NOTIFY handling understand and use the nsm_handle.
To make it a bit clear what is happening:
nlmclent_prepare_reclaim and nlmclnt_finish_reclaim
get open-coded into 'reclaimer'
The result is tidied up.
Then some of that functionality is moved out into nlm_host_rebooted (which
calls nlmclnt_recovery which starts a thread which runs reclaimer).
Also host_rebooted now finds an nsm_handle rather than a host, then then
iterates over all hosts and deals with each host that shares that nsm_handle.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/lockd/clntlock.c | 55 | ||||
-rw-r--r-- | fs/lockd/host.c | 63 | ||||
-rw-r--r-- | fs/lockd/svc4proc.c | 2 | ||||
-rw-r--r-- | fs/lockd/svcproc.c | 2 | ||||
-rw-r--r-- | include/linux/lockd/lockd.h | 4 |
5 files changed, 69 insertions, 57 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 54e63ddef043..a4ab6dd7661f 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c | |||
@@ -144,43 +144,12 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) | |||
144 | */ | 144 | */ |
145 | 145 | ||
146 | /* | 146 | /* |
147 | * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number, | ||
148 | * that we mark locks for reclaiming, and that we bump the pseudo NSM state. | ||
149 | */ | ||
150 | static void nlmclnt_prepare_reclaim(struct nlm_host *host) | ||
151 | { | ||
152 | down_write(&host->h_rwsem); | ||
153 | if (host->h_nsmhandle) | ||
154 | host->h_nsmhandle->sm_monitored = 0; | ||
155 | host->h_state++; | ||
156 | host->h_nextrebind = 0; | ||
157 | nlm_rebind_host(host); | ||
158 | |||
159 | /* | ||
160 | * Mark the locks for reclaiming. | ||
161 | */ | ||
162 | list_splice_init(&host->h_granted, &host->h_reclaim); | ||
163 | |||
164 | dprintk("NLM: reclaiming locks for host %s\n", host->h_name); | ||
165 | } | ||
166 | |||
167 | static void nlmclnt_finish_reclaim(struct nlm_host *host) | ||
168 | { | ||
169 | host->h_reclaiming = 0; | ||
170 | up_write(&host->h_rwsem); | ||
171 | dprintk("NLM: done reclaiming locks for host %s", host->h_name); | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * Reclaim all locks on server host. We do this by spawning a separate | 147 | * Reclaim all locks on server host. We do this by spawning a separate |
176 | * reclaimer thread. | 148 | * reclaimer thread. |
177 | */ | 149 | */ |
178 | void | 150 | void |
179 | nlmclnt_recovery(struct nlm_host *host, u32 newstate) | 151 | nlmclnt_recovery(struct nlm_host *host) |
180 | { | 152 | { |
181 | if (host->h_nsmstate == newstate) | ||
182 | return; | ||
183 | host->h_nsmstate = newstate; | ||
184 | if (!host->h_reclaiming++) { | 153 | if (!host->h_reclaiming++) { |
185 | nlm_get_host(host); | 154 | nlm_get_host(host); |
186 | __module_get(THIS_MODULE); | 155 | __module_get(THIS_MODULE); |
@@ -200,18 +169,30 @@ reclaimer(void *ptr) | |||
200 | daemonize("%s-reclaim", host->h_name); | 169 | daemonize("%s-reclaim", host->h_name); |
201 | allow_signal(SIGKILL); | 170 | allow_signal(SIGKILL); |
202 | 171 | ||
172 | down_write(&host->h_rwsem); | ||
173 | |||
203 | /* This one ensures that our parent doesn't terminate while the | 174 | /* This one ensures that our parent doesn't terminate while the |
204 | * reclaim is in progress */ | 175 | * reclaim is in progress */ |
205 | lock_kernel(); | 176 | lock_kernel(); |
206 | lockd_up(0); /* note: this cannot fail as lockd is already running */ | 177 | lockd_up(0); /* note: this cannot fail as lockd is already running */ |
207 | 178 | ||
208 | nlmclnt_prepare_reclaim(host); | 179 | dprintk("lockd: reclaiming locks for host %s", host->h_name); |
209 | /* First, reclaim all locks that have been marked. */ | 180 | |
210 | restart: | 181 | restart: |
211 | nsmstate = host->h_nsmstate; | 182 | nsmstate = host->h_nsmstate; |
183 | |||
184 | /* Force a portmap getport - the peer's lockd will | ||
185 | * most likely end up on a different port. | ||
186 | */ | ||
187 | host->h_nextrebind = 0; | ||
188 | nlm_rebind_host(host); | ||
189 | |||
190 | /* First, reclaim all locks that have been granted. */ | ||
191 | list_splice_init(&host->h_granted, &host->h_reclaim); | ||
212 | list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) { | 192 | list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) { |
213 | list_del_init(&fl->fl_u.nfs_fl.list); | 193 | list_del_init(&fl->fl_u.nfs_fl.list); |
214 | 194 | ||
195 | /* Why are we leaking memory here? --okir */ | ||
215 | if (signalled()) | 196 | if (signalled()) |
216 | continue; | 197 | continue; |
217 | if (nlmclnt_reclaim(host, fl) != 0) | 198 | if (nlmclnt_reclaim(host, fl) != 0) |
@@ -219,11 +200,13 @@ restart: | |||
219 | list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); | 200 | list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); |
220 | if (host->h_nsmstate != nsmstate) { | 201 | if (host->h_nsmstate != nsmstate) { |
221 | /* Argh! The server rebooted again! */ | 202 | /* Argh! The server rebooted again! */ |
222 | list_splice_init(&host->h_granted, &host->h_reclaim); | ||
223 | goto restart; | 203 | goto restart; |
224 | } | 204 | } |
225 | } | 205 | } |
226 | nlmclnt_finish_reclaim(host); | 206 | |
207 | host->h_reclaiming = 0; | ||
208 | up_write(&host->h_rwsem); | ||
209 | dprintk("NLM: done reclaiming locks for host %s", host->h_name); | ||
227 | 210 | ||
228 | /* Now, wake up all processes that sleep on a blocked lock */ | 211 | /* Now, wake up all processes that sleep on a blocked lock */ |
229 | list_for_each_entry(block, &nlm_blocked, b_list) { | 212 | list_for_each_entry(block, &nlm_blocked, b_list) { |
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 4990223a3e18..3cd96e2e1256 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
@@ -290,28 +290,57 @@ void nlm_release_host(struct nlm_host *host) | |||
290 | * has rebooted. | 290 | * has rebooted. |
291 | * Release all resources held by that peer. | 291 | * Release all resources held by that peer. |
292 | */ | 292 | */ |
293 | void nlm_host_rebooted(const struct sockaddr_in *sin, const struct nlm_reboot *argp) | 293 | void nlm_host_rebooted(const struct sockaddr_in *sin, |
294 | const char *hostname, int hostname_len, | ||
295 | u32 new_state) | ||
294 | { | 296 | { |
295 | struct nlm_host *host; | 297 | struct nsm_handle *nsm; |
296 | int server; | 298 | struct nlm_host *host, **hp; |
299 | int hash; | ||
297 | 300 | ||
298 | /* Obtain the host pointer for this NFS server and try to | 301 | dprintk("lockd: nlm_host_rebooted(%s, %u.%u.%u.%u)\n", |
299 | * reclaim all locks we hold on this server. | 302 | hostname, NIPQUAD(sin->sin_addr)); |
300 | */ | 303 | |
301 | server = (argp->proto & 1)? 1 : 0; | 304 | /* Find the NSM handle for this peer */ |
302 | host = nlm_lookup_host(server, sin, argp->proto >> 1, argp->vers, | 305 | if (!(nsm = __nsm_find(sin, hostname, hostname_len, 0))) |
303 | argp->mon, argp->len); | ||
304 | if (host == NULL) | ||
305 | return; | 306 | return; |
306 | 307 | ||
307 | if (server == 0) { | 308 | /* When reclaiming locks on this peer, make sure that |
308 | /* We are client, he's the server: try to reclaim all locks. */ | 309 | * we set up a new notification */ |
309 | nlmclnt_recovery(host, argp->state); | 310 | nsm->sm_monitored = 0; |
310 | } else { | 311 | |
311 | /* He's the client, we're the server: delete all locks held by the client */ | 312 | /* Mark all hosts tied to this NSM state as having rebooted. |
312 | nlmsvc_free_host_resources(host); | 313 | * We run the loop repeatedly, because we drop the host table |
314 | * lock for this. | ||
315 | * To avoid processing a host several times, we match the nsmstate. | ||
316 | */ | ||
317 | again: mutex_lock(&nlm_host_mutex); | ||
318 | for (hash = 0; hash < NLM_HOST_NRHASH; hash++) { | ||
319 | for (hp = &nlm_hosts[hash]; (host = *hp); hp = &host->h_next) { | ||
320 | if (host->h_nsmhandle == nsm | ||
321 | && host->h_nsmstate != new_state) { | ||
322 | host->h_nsmstate = new_state; | ||
323 | host->h_state++; | ||
324 | |||
325 | nlm_get_host(host); | ||
326 | mutex_unlock(&nlm_host_mutex); | ||
327 | |||
328 | if (host->h_server) { | ||
329 | /* We're server for this guy, just ditch | ||
330 | * all the locks he held. */ | ||
331 | nlmsvc_free_host_resources(host); | ||
332 | } else { | ||
333 | /* He's the server, initiate lock recovery. */ | ||
334 | nlmclnt_recovery(host); | ||
335 | } | ||
336 | |||
337 | nlm_release_host(host); | ||
338 | goto again; | ||
339 | } | ||
340 | } | ||
313 | } | 341 | } |
314 | nlm_release_host(host); | 342 | |
343 | mutex_unlock(&nlm_host_mutex); | ||
315 | } | 344 | } |
316 | 345 | ||
317 | /* | 346 | /* |
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index 7d835ad81074..b8525fb62934 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c | |||
@@ -438,7 +438,7 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, | |||
438 | */ | 438 | */ |
439 | memset(&saddr, 0, sizeof(saddr)); | 439 | memset(&saddr, 0, sizeof(saddr)); |
440 | saddr.sin_addr.s_addr = argp->addr; | 440 | saddr.sin_addr.s_addr = argp->addr; |
441 | nlm_host_rebooted(&saddr, argp); | 441 | nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state); |
442 | 442 | ||
443 | return rpc_success; | 443 | return rpc_success; |
444 | } | 444 | } |
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 12291ab1e722..66e7b0b3430e 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c | |||
@@ -467,7 +467,7 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, | |||
467 | */ | 467 | */ |
468 | memset(&saddr, 0, sizeof(saddr)); | 468 | memset(&saddr, 0, sizeof(saddr)); |
469 | saddr.sin_addr.s_addr = argp->addr; | 469 | saddr.sin_addr.s_addr = argp->addr; |
470 | nlm_host_rebooted(&saddr, argp); | 470 | nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state); |
471 | 471 | ||
472 | return rpc_success; | 472 | return rpc_success; |
473 | } | 473 | } |
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index ab2ffc8a0b44..a41eb841428b 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h | |||
@@ -164,7 +164,7 @@ struct nlm_wait * nlmclnt_prepare_block(struct nlm_host *host, struct file_lock | |||
164 | void nlmclnt_finish_block(struct nlm_wait *block); | 164 | void nlmclnt_finish_block(struct nlm_wait *block); |
165 | int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout); | 165 | int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout); |
166 | u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *); | 166 | u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *); |
167 | void nlmclnt_recovery(struct nlm_host *, u32); | 167 | void nlmclnt_recovery(struct nlm_host *); |
168 | int nlmclnt_reclaim(struct nlm_host *, struct file_lock *); | 168 | int nlmclnt_reclaim(struct nlm_host *, struct file_lock *); |
169 | 169 | ||
170 | /* | 170 | /* |
@@ -179,7 +179,7 @@ struct nlm_host * nlm_get_host(struct nlm_host *); | |||
179 | void nlm_release_host(struct nlm_host *); | 179 | void nlm_release_host(struct nlm_host *); |
180 | void nlm_shutdown_hosts(void); | 180 | void nlm_shutdown_hosts(void); |
181 | extern struct nlm_host *nlm_find_client(void); | 181 | extern struct nlm_host *nlm_find_client(void); |
182 | extern void nlm_host_rebooted(const struct sockaddr_in *, const struct nlm_reboot *); | 182 | extern void nlm_host_rebooted(const struct sockaddr_in *, const char *, int, u32); |
183 | struct nsm_handle *nsm_find(const struct sockaddr_in *, const char *, int); | 183 | struct nsm_handle *nsm_find(const struct sockaddr_in *, const char *, int); |
184 | void nsm_release(struct nsm_handle *); | 184 | void nsm_release(struct nsm_handle *); |
185 | 185 | ||