[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>
This commit is contained in:
parent
f0737a39a6
commit
5c8dd29ca7
|
@ -143,44 +143,13 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock)
|
||||||
* server crash.
|
* server crash.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number,
|
|
||||||
* that we mark locks for reclaiming, and that we bump the pseudo NSM state.
|
|
||||||
*/
|
|
||||||
static void nlmclnt_prepare_reclaim(struct nlm_host *host)
|
|
||||||
{
|
|
||||||
down_write(&host->h_rwsem);
|
|
||||||
if (host->h_nsmhandle)
|
|
||||||
host->h_nsmhandle->sm_monitored = 0;
|
|
||||||
host->h_state++;
|
|
||||||
host->h_nextrebind = 0;
|
|
||||||
nlm_rebind_host(host);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Mark the locks for reclaiming.
|
|
||||||
*/
|
|
||||||
list_splice_init(&host->h_granted, &host->h_reclaim);
|
|
||||||
|
|
||||||
dprintk("NLM: reclaiming locks for host %s\n", host->h_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nlmclnt_finish_reclaim(struct nlm_host *host)
|
|
||||||
{
|
|
||||||
host->h_reclaiming = 0;
|
|
||||||
up_write(&host->h_rwsem);
|
|
||||||
dprintk("NLM: done reclaiming locks for host %s", host->h_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reclaim all locks on server host. We do this by spawning a separate
|
* Reclaim all locks on server host. We do this by spawning a separate
|
||||||
* reclaimer thread.
|
* reclaimer thread.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
nlmclnt_recovery(struct nlm_host *host, u32 newstate)
|
nlmclnt_recovery(struct nlm_host *host)
|
||||||
{
|
{
|
||||||
if (host->h_nsmstate == newstate)
|
|
||||||
return;
|
|
||||||
host->h_nsmstate = newstate;
|
|
||||||
if (!host->h_reclaiming++) {
|
if (!host->h_reclaiming++) {
|
||||||
nlm_get_host(host);
|
nlm_get_host(host);
|
||||||
__module_get(THIS_MODULE);
|
__module_get(THIS_MODULE);
|
||||||
|
@ -200,18 +169,30 @@ reclaimer(void *ptr)
|
||||||
daemonize("%s-reclaim", host->h_name);
|
daemonize("%s-reclaim", host->h_name);
|
||||||
allow_signal(SIGKILL);
|
allow_signal(SIGKILL);
|
||||||
|
|
||||||
|
down_write(&host->h_rwsem);
|
||||||
|
|
||||||
/* This one ensures that our parent doesn't terminate while the
|
/* This one ensures that our parent doesn't terminate while the
|
||||||
* reclaim is in progress */
|
* reclaim is in progress */
|
||||||
lock_kernel();
|
lock_kernel();
|
||||||
lockd_up(0); /* note: this cannot fail as lockd is already running */
|
lockd_up(0); /* note: this cannot fail as lockd is already running */
|
||||||
|
|
||||||
nlmclnt_prepare_reclaim(host);
|
dprintk("lockd: reclaiming locks for host %s", host->h_name);
|
||||||
/* First, reclaim all locks that have been marked. */
|
|
||||||
restart:
|
restart:
|
||||||
nsmstate = host->h_nsmstate;
|
nsmstate = host->h_nsmstate;
|
||||||
|
|
||||||
|
/* Force a portmap getport - the peer's lockd will
|
||||||
|
* most likely end up on a different port.
|
||||||
|
*/
|
||||||
|
host->h_nextrebind = 0;
|
||||||
|
nlm_rebind_host(host);
|
||||||
|
|
||||||
|
/* First, reclaim all locks that have been granted. */
|
||||||
|
list_splice_init(&host->h_granted, &host->h_reclaim);
|
||||||
list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) {
|
list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) {
|
||||||
list_del_init(&fl->fl_u.nfs_fl.list);
|
list_del_init(&fl->fl_u.nfs_fl.list);
|
||||||
|
|
||||||
|
/* Why are we leaking memory here? --okir */
|
||||||
if (signalled())
|
if (signalled())
|
||||||
continue;
|
continue;
|
||||||
if (nlmclnt_reclaim(host, fl) != 0)
|
if (nlmclnt_reclaim(host, fl) != 0)
|
||||||
|
@ -219,11 +200,13 @@ restart:
|
||||||
list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted);
|
list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted);
|
||||||
if (host->h_nsmstate != nsmstate) {
|
if (host->h_nsmstate != nsmstate) {
|
||||||
/* Argh! The server rebooted again! */
|
/* Argh! The server rebooted again! */
|
||||||
list_splice_init(&host->h_granted, &host->h_reclaim);
|
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nlmclnt_finish_reclaim(host);
|
|
||||||
|
host->h_reclaiming = 0;
|
||||||
|
up_write(&host->h_rwsem);
|
||||||
|
dprintk("NLM: done reclaiming locks for host %s", host->h_name);
|
||||||
|
|
||||||
/* Now, wake up all processes that sleep on a blocked lock */
|
/* Now, wake up all processes that sleep on a blocked lock */
|
||||||
list_for_each_entry(block, &nlm_blocked, b_list) {
|
list_for_each_entry(block, &nlm_blocked, b_list) {
|
||||||
|
|
|
@ -290,28 +290,57 @@ void nlm_release_host(struct nlm_host *host)
|
||||||
* has rebooted.
|
* has rebooted.
|
||||||
* Release all resources held by that peer.
|
* Release all resources held by that peer.
|
||||||
*/
|
*/
|
||||||
void nlm_host_rebooted(const struct sockaddr_in *sin, const struct nlm_reboot *argp)
|
void nlm_host_rebooted(const struct sockaddr_in *sin,
|
||||||
|
const char *hostname, int hostname_len,
|
||||||
|
u32 new_state)
|
||||||
{
|
{
|
||||||
struct nlm_host *host;
|
struct nsm_handle *nsm;
|
||||||
int server;
|
struct nlm_host *host, **hp;
|
||||||
|
int hash;
|
||||||
|
|
||||||
/* Obtain the host pointer for this NFS server and try to
|
dprintk("lockd: nlm_host_rebooted(%s, %u.%u.%u.%u)\n",
|
||||||
* reclaim all locks we hold on this server.
|
hostname, NIPQUAD(sin->sin_addr));
|
||||||
*/
|
|
||||||
server = (argp->proto & 1)? 1 : 0;
|
/* Find the NSM handle for this peer */
|
||||||
host = nlm_lookup_host(server, sin, argp->proto >> 1, argp->vers,
|
if (!(nsm = __nsm_find(sin, hostname, hostname_len, 0)))
|
||||||
argp->mon, argp->len);
|
|
||||||
if (host == NULL)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (server == 0) {
|
/* When reclaiming locks on this peer, make sure that
|
||||||
/* We are client, he's the server: try to reclaim all locks. */
|
* we set up a new notification */
|
||||||
nlmclnt_recovery(host, argp->state);
|
nsm->sm_monitored = 0;
|
||||||
} else {
|
|
||||||
/* He's the client, we're the server: delete all locks held by the client */
|
/* Mark all hosts tied to this NSM state as having rebooted.
|
||||||
nlmsvc_free_host_resources(host);
|
* We run the loop repeatedly, because we drop the host table
|
||||||
|
* lock for this.
|
||||||
|
* To avoid processing a host several times, we match the nsmstate.
|
||||||
|
*/
|
||||||
|
again: mutex_lock(&nlm_host_mutex);
|
||||||
|
for (hash = 0; hash < NLM_HOST_NRHASH; hash++) {
|
||||||
|
for (hp = &nlm_hosts[hash]; (host = *hp); hp = &host->h_next) {
|
||||||
|
if (host->h_nsmhandle == nsm
|
||||||
|
&& host->h_nsmstate != new_state) {
|
||||||
|
host->h_nsmstate = new_state;
|
||||||
|
host->h_state++;
|
||||||
|
|
||||||
|
nlm_get_host(host);
|
||||||
|
mutex_unlock(&nlm_host_mutex);
|
||||||
|
|
||||||
|
if (host->h_server) {
|
||||||
|
/* We're server for this guy, just ditch
|
||||||
|
* all the locks he held. */
|
||||||
|
nlmsvc_free_host_resources(host);
|
||||||
|
} else {
|
||||||
|
/* He's the server, initiate lock recovery. */
|
||||||
|
nlmclnt_recovery(host);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlm_release_host(host);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
nlm_release_host(host);
|
|
||||||
|
mutex_unlock(&nlm_host_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -438,7 +438,7 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
|
||||||
*/
|
*/
|
||||||
memset(&saddr, 0, sizeof(saddr));
|
memset(&saddr, 0, sizeof(saddr));
|
||||||
saddr.sin_addr.s_addr = argp->addr;
|
saddr.sin_addr.s_addr = argp->addr;
|
||||||
nlm_host_rebooted(&saddr, argp);
|
nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state);
|
||||||
|
|
||||||
return rpc_success;
|
return rpc_success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -467,7 +467,7 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
|
||||||
*/
|
*/
|
||||||
memset(&saddr, 0, sizeof(saddr));
|
memset(&saddr, 0, sizeof(saddr));
|
||||||
saddr.sin_addr.s_addr = argp->addr;
|
saddr.sin_addr.s_addr = argp->addr;
|
||||||
nlm_host_rebooted(&saddr, argp);
|
nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state);
|
||||||
|
|
||||||
return rpc_success;
|
return rpc_success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ struct nlm_wait * nlmclnt_prepare_block(struct nlm_host *host, struct file_lock
|
||||||
void nlmclnt_finish_block(struct nlm_wait *block);
|
void nlmclnt_finish_block(struct nlm_wait *block);
|
||||||
int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout);
|
int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout);
|
||||||
u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *);
|
u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *);
|
||||||
void nlmclnt_recovery(struct nlm_host *, u32);
|
void nlmclnt_recovery(struct nlm_host *);
|
||||||
int nlmclnt_reclaim(struct nlm_host *, struct file_lock *);
|
int nlmclnt_reclaim(struct nlm_host *, struct file_lock *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -179,7 +179,7 @@ struct nlm_host * nlm_get_host(struct nlm_host *);
|
||||||
void nlm_release_host(struct nlm_host *);
|
void nlm_release_host(struct nlm_host *);
|
||||||
void nlm_shutdown_hosts(void);
|
void nlm_shutdown_hosts(void);
|
||||||
extern struct nlm_host *nlm_find_client(void);
|
extern struct nlm_host *nlm_find_client(void);
|
||||||
extern void nlm_host_rebooted(const struct sockaddr_in *, const struct nlm_reboot *);
|
extern void nlm_host_rebooted(const struct sockaddr_in *, const char *, int, u32);
|
||||||
struct nsm_handle *nsm_find(const struct sockaddr_in *, const char *, int);
|
struct nsm_handle *nsm_find(const struct sockaddr_in *, const char *, int);
|
||||||
void nsm_release(struct nsm_handle *);
|
void nsm_release(struct nsm_handle *);
|
||||||
|
|
||||||
|
|
Reference in New Issue