diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2008-12-05 19:03:46 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-01-06 11:53:54 -0500 |
commit | 3420a8c4359a189f7d854ed7075d151257415447 (patch) | |
tree | dbcfbcdd9383bc4a9bb832f6b4a8876461495dc8 /fs/lockd/mon.c | |
parent | 576df4634e37e46b441fefb91915184edb13bb94 (diff) |
NSM: Add nsm_lookup() function
Introduce a new API to fs/lockd/mon.c that allows nlm_host_rebooted()
to lookup up nsm_handles via the contents of an nlm_reboot struct.
The new function is equivalent to calling nsm_find() with @create set
to zero, but it takes a struct nlm_reboot instead of separate
arguments.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs/lockd/mon.c')
-rw-r--r-- | fs/lockd/mon.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 4424b0a5a51f..e46903995c99 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -201,6 +201,29 @@ void nsm_unmonitor(const struct nlm_host *host) } } +static struct nsm_handle *nsm_lookup_hostname(const char *hostname, + const size_t len) +{ + struct nsm_handle *nsm; + + list_for_each_entry(nsm, &nsm_handles, sm_link) + if (strlen(nsm->sm_name) == len && + memcmp(nsm->sm_name, hostname, len) == 0) + return nsm; + return NULL; +} + +static struct nsm_handle *nsm_lookup_priv(const struct nsm_private *priv) +{ + struct nsm_handle *nsm; + + list_for_each_entry(nsm, &nsm_handles, sm_link) + if (memcmp(nsm->sm_priv.data, priv->data, + sizeof(priv->data)) == 0) + return nsm; + return NULL; +} + /* * Construct a unique cookie to match this nsm_handle to this monitored * host. It is passed to the local rpc.statd via NSMPROC_MON, and @@ -298,6 +321,47 @@ found: } /** + * nsm_reboot_lookup - match NLMPROC_SM_NOTIFY arguments to an nsm_handle + * @info: pointer to NLMPROC_SM_NOTIFY arguments + * + * Returns a matching nsm_handle if found in the nsm cache; the returned + * nsm_handle's reference count is bumped and sm_monitored is cleared. + * Otherwise returns NULL if some error occurred. + */ +struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info) +{ + struct nsm_handle *cached; + + spin_lock(&nsm_lock); + + if (nsm_use_hostnames && info->mon != NULL) + cached = nsm_lookup_hostname(info->mon, info->len); + else + cached = nsm_lookup_priv(&info->priv); + + if (unlikely(cached == NULL)) { + spin_unlock(&nsm_lock); + dprintk("lockd: never saw rebooted peer '%.*s' before\n", + info->len, info->mon); + return cached; + } + + atomic_inc(&cached->sm_count); + spin_unlock(&nsm_lock); + + /* + * During subsequent lock activity, force a fresh + * notification to be set up for this host. + */ + cached->sm_monitored = 0; + + dprintk("lockd: host %s (%s) rebooted, cnt %d\n", + cached->sm_name, cached->sm_addrbuf, + atomic_read(&cached->sm_count)); + return cached; +} + +/** * nsm_release - Release an NSM handle * @nsm: pointer to handle to be released * |