diff options
-rw-r--r-- | fs/lockd/mon.c | 64 | ||||
-rw-r--r-- | include/linux/lockd/lockd.h | 1 |
2 files changed, 65 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) | |||
201 | } | 201 | } |
202 | } | 202 | } |
203 | 203 | ||
204 | static struct nsm_handle *nsm_lookup_hostname(const char *hostname, | ||
205 | const size_t len) | ||
206 | { | ||
207 | struct nsm_handle *nsm; | ||
208 | |||
209 | list_for_each_entry(nsm, &nsm_handles, sm_link) | ||
210 | if (strlen(nsm->sm_name) == len && | ||
211 | memcmp(nsm->sm_name, hostname, len) == 0) | ||
212 | return nsm; | ||
213 | return NULL; | ||
214 | } | ||
215 | |||
216 | static struct nsm_handle *nsm_lookup_priv(const struct nsm_private *priv) | ||
217 | { | ||
218 | struct nsm_handle *nsm; | ||
219 | |||
220 | list_for_each_entry(nsm, &nsm_handles, sm_link) | ||
221 | if (memcmp(nsm->sm_priv.data, priv->data, | ||
222 | sizeof(priv->data)) == 0) | ||
223 | return nsm; | ||
224 | return NULL; | ||
225 | } | ||
226 | |||
204 | /* | 227 | /* |
205 | * Construct a unique cookie to match this nsm_handle to this monitored | 228 | * Construct a unique cookie to match this nsm_handle to this monitored |
206 | * host. It is passed to the local rpc.statd via NSMPROC_MON, and | 229 | * host. It is passed to the local rpc.statd via NSMPROC_MON, and |
@@ -298,6 +321,47 @@ found: | |||
298 | } | 321 | } |
299 | 322 | ||
300 | /** | 323 | /** |
324 | * nsm_reboot_lookup - match NLMPROC_SM_NOTIFY arguments to an nsm_handle | ||
325 | * @info: pointer to NLMPROC_SM_NOTIFY arguments | ||
326 | * | ||
327 | * Returns a matching nsm_handle if found in the nsm cache; the returned | ||
328 | * nsm_handle's reference count is bumped and sm_monitored is cleared. | ||
329 | * Otherwise returns NULL if some error occurred. | ||
330 | */ | ||
331 | struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info) | ||
332 | { | ||
333 | struct nsm_handle *cached; | ||
334 | |||
335 | spin_lock(&nsm_lock); | ||
336 | |||
337 | if (nsm_use_hostnames && info->mon != NULL) | ||
338 | cached = nsm_lookup_hostname(info->mon, info->len); | ||
339 | else | ||
340 | cached = nsm_lookup_priv(&info->priv); | ||
341 | |||
342 | if (unlikely(cached == NULL)) { | ||
343 | spin_unlock(&nsm_lock); | ||
344 | dprintk("lockd: never saw rebooted peer '%.*s' before\n", | ||
345 | info->len, info->mon); | ||
346 | return cached; | ||
347 | } | ||
348 | |||
349 | atomic_inc(&cached->sm_count); | ||
350 | spin_unlock(&nsm_lock); | ||
351 | |||
352 | /* | ||
353 | * During subsequent lock activity, force a fresh | ||
354 | * notification to be set up for this host. | ||
355 | */ | ||
356 | cached->sm_monitored = 0; | ||
357 | |||
358 | dprintk("lockd: host %s (%s) rebooted, cnt %d\n", | ||
359 | cached->sm_name, cached->sm_addrbuf, | ||
360 | atomic_read(&cached->sm_count)); | ||
361 | return cached; | ||
362 | } | ||
363 | |||
364 | /** | ||
301 | * nsm_release - Release an NSM handle | 365 | * nsm_release - Release an NSM handle |
302 | * @nsm: pointer to handle to be released | 366 | * @nsm: pointer to handle to be released |
303 | * | 367 | * |
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 2a3533ea38dd..5e3ad926de89 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h | |||
@@ -251,6 +251,7 @@ struct nsm_handle *nsm_find(const struct sockaddr *sap, const size_t salen, | |||
251 | const char *hostname, | 251 | const char *hostname, |
252 | const size_t hostname_len, | 252 | const size_t hostname_len, |
253 | const int create); | 253 | const int create); |
254 | struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info); | ||
254 | void nsm_release(struct nsm_handle *nsm); | 255 | void nsm_release(struct nsm_handle *nsm); |
255 | 256 | ||
256 | /* | 257 | /* |