summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Dagnelie <paul.dagnelie@delphix.com>2015-01-19 09:58:35 -0800
committerChristopher Siden <chris@delphix.com>2015-01-19 09:58:35 -0800
commit096e63b2c66f47e2a2d213edc199cdb082d8b2d6 (patch)
tree9823222fa51b33d82805e861a3e962f3f5443088
parent18059eae28246ed2eef942a16364131202558094 (diff)
downloadillumos-joyent-096e63b2c66f47e2a2d213edc199cdb082d8b2d6.tar.gz
4872 system crash after nlm_gc hits bogus mutex
Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Christopher Siden <christopher.siden@delphix.com> Reviewed by: Eric Schrock <eric.schrock@delphix.com> Reviewed by: Jeremy Jones <jeremy@delphix.com> Approved by: Garrett D'Amore <garrett@damore.org>
-rw-r--r--usr/src/uts/common/klm/nlm_impl.c25
1 files changed, 13 insertions, 12 deletions
diff --git a/usr/src/uts/common/klm/nlm_impl.c b/usr/src/uts/common/klm/nlm_impl.c
index 7daa30dcb3..a10ba86a6e 100644
--- a/usr/src/uts/common/klm/nlm_impl.c
+++ b/usr/src/uts/common/klm/nlm_impl.c
@@ -398,23 +398,23 @@ nlm_gc(struct nlm_globals *g)
mutex_enter(&g->lock);
/*
- * While we were doing expensive operations outside of
- * nlm_globals critical section, somebody could
- * take the host, add lock/share to one of its vnodes
- * and release the host back. If so, host's idle timeout
- * is renewed and our information about locks on the
- * given host is outdated.
+ * While we were doing expensive operations
+ * outside of nlm_globals critical section,
+ * somebody could take the host and remove it
+ * from the idle list. Whether its been
+ * reinserted or not, our information about
+ * the host is outdated, and we should take no
+ * further action.
*/
- if (hostp->nh_idle_timeout > now)
+ if (hostp->nh_idle_timeout > now || hostp->nh_refs > 0)
continue;
/*
- * If either host has locks or somebody has began to
- * use it while we were outside the nlm_globals critical
- * section. In both cases we have to renew host's
- * timeout and put it to the end of LRU list.
+ * If the host has locks we have to renew the
+ * host's timeout and put it at the end of LRU
+ * list.
*/
- if (has_locks || hostp->nh_refs > 0) {
+ if (has_locks) {
TAILQ_REMOVE(&g->nlm_idle_hosts,
hostp, nh_link);
hostp->nh_idle_timeout = now + idle_period;
@@ -1139,6 +1139,7 @@ static void
nlm_host_unregister(struct nlm_globals *g, struct nlm_host *hostp)
{
ASSERT(hostp->nh_refs == 0);
+ ASSERT(hostp->nh_flags & NLM_NH_INIDLE);
avl_remove(&g->nlm_hosts_tree, hostp);
VERIFY(mod_hash_remove(g->nlm_hosts_hash,