aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlaf Kirch <okir@suse.de>2006-10-04 05:15:55 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:17 -0400
commit5c8dd29ca7fc7483690cef4306549742d534f2a2 (patch)
treeedf51e354535448ea6b57a59358d9f28c556684c
parentf0737a39a64a9df32bb045c54e1cdf6cecdcbdd7 (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.c55
-rw-r--r--fs/lockd/host.c63
-rw-r--r--fs/lockd/svc4proc.c2
-rw-r--r--fs/lockd/svcproc.c2
-rw-r--r--include/linux/lockd/lockd.h4
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 */
150static 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
167static 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 */
178void 150void
179nlmclnt_recovery(struct nlm_host *host, u32 newstate) 151nlmclnt_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
210restart: 181restart:
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 */
293void nlm_host_rebooted(const struct sockaddr_in *sin, const struct nlm_reboot *argp) 293void 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 */
317again: 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
164void nlmclnt_finish_block(struct nlm_wait *block); 164void nlmclnt_finish_block(struct nlm_wait *block);
165int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout); 165int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout);
166u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *); 166u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *);
167void nlmclnt_recovery(struct nlm_host *, u32); 167void nlmclnt_recovery(struct nlm_host *);
168int nlmclnt_reclaim(struct nlm_host *, struct file_lock *); 168int 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 *);
179void nlm_release_host(struct nlm_host *); 179void nlm_release_host(struct nlm_host *);
180void nlm_shutdown_hosts(void); 180void nlm_shutdown_hosts(void);
181extern struct nlm_host *nlm_find_client(void); 181extern struct nlm_host *nlm_find_client(void);
182extern void nlm_host_rebooted(const struct sockaddr_in *, const struct nlm_reboot *); 182extern void nlm_host_rebooted(const struct sockaddr_in *, const char *, int, u32);
183struct nsm_handle *nsm_find(const struct sockaddr_in *, const char *, int); 183struct nsm_handle *nsm_find(const struct sockaddr_in *, const char *, int);
184void nsm_release(struct nsm_handle *); 184void nsm_release(struct nsm_handle *);
185 185