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 | */ |
