summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorthurlow <none@none>2005-07-29 16:17:08 -0700
committerthurlow <none@none>2005-07-29 16:17:08 -0700
commit3fd6cc295d1c8c721b4b8abb49bbe0fefe51d034 (patch)
treeb5473bf5a24b74a6db9fd957ecc27099df913854 /usr/src
parent0ab54cfb0b7bb7b02cb898cc6c9f6a36237410c4 (diff)
downloadillumos-joyent-3fd6cc295d1c8c721b4b8abb49bbe0fefe51d034.tar.gz
6266836 panic: recursive mutex acquisition in nfs_mi_zonelist_remove()
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_client.c21
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_client.c25
-rw-r--r--usr/src/uts/common/nfs/nfs4_clnt.h2
-rw-r--r--usr/src/uts/common/nfs/nfs_clnt.h1
4 files changed, 47 insertions, 2 deletions
diff --git a/usr/src/uts/common/fs/nfs/nfs4_client.c b/usr/src/uts/common/fs/nfs/nfs4_client.c
index 3e7d8d3cd1..f641944f48 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_client.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_client.c
@@ -2785,11 +2785,24 @@ nfs4_mi_shutdown(zoneid_t zoneid, void *data)
NFS4_DEBUG(nfs4_client_zone_debug, (CE_NOTE,
"nfs4_mi_shutdown zone %d\n", zoneid));
ASSERT(mig != NULL);
+again:
mutex_enter(&mig->mig_lock);
for (mi = list_head(&mig->mig_list); mi != NULL;
mi = list_next(&mig->mig_list, mi)) {
+ /*
+ * If we've done the shutdown work for this FS, skip.
+ * Once we go off the end of the list, we're done.
+ */
+ if (mi->mi_flags & MI4_DEAD)
+ continue;
+
+ /*
+ * We will do work, so not done. Get a hold on the FS.
+ */
NFS4_DEBUG(nfs4_client_zone_debug, (CE_NOTE,
"nfs4_mi_shutdown stopping vfs %p\n", (void *)mi->mi_vfsp));
+ VFS_HOLD(mi->mi_vfsp);
+
/*
* purge the DNLC for this filesystem
*/
@@ -2815,6 +2828,14 @@ nfs4_mi_shutdown(zoneid_t zoneid, void *data)
*/
cv_broadcast(&mi->mi_async_reqs_cv);
mutex_exit(&mi->mi_async_lock);
+
+ /*
+ * Drop lock and release FS, which may change list, then repeat.
+ * We're done when every mi has been done or the list is empty.
+ */
+ mutex_exit(&mig->mig_lock);
+ VFS_RELE(mi->mi_vfsp);
+ goto again;
}
mutex_exit(&mig->mig_lock);
/*
diff --git a/usr/src/uts/common/fs/nfs/nfs_client.c b/usr/src/uts/common/fs/nfs/nfs_client.c
index 8ec8a2cadd..ebc430d4c4 100644
--- a/usr/src/uts/common/fs/nfs/nfs_client.c
+++ b/usr/src/uts/common/fs/nfs/nfs_client.c
@@ -2518,9 +2518,23 @@ nfs_mi_shutdown(zoneid_t zoneid, void *data)
mntinfo_t *mi;
ASSERT(mig != NULL);
+again:
mutex_enter(&mig->mig_lock);
for (mi = list_head(&mig->mig_list); mi != NULL;
mi = list_next(&mig->mig_list, mi)) {
+
+ /*
+ * If we've done the shutdown work for this FS, skip.
+ * Once we go off the end of the list, we're done.
+ */
+ if (mi->mi_flags & MI_DEAD)
+ continue;
+
+ /*
+ * We will do work, so not done. Get a hold on the FS.
+ */
+ VFS_HOLD(mi->mi_vfsp);
+
/*
* purge the DNLC for this filesystem
*/
@@ -2535,15 +2549,24 @@ nfs_mi_shutdown(zoneid_t zoneid, void *data)
/*
* Set MI_ASYNC_MGR_STOP so the async manager thread starts
* getting ready to exit when it's done with its current work.
+ * Also set MI_DEAD to note we've acted on this FS.
*/
mutex_enter(&mi->mi_lock);
- mi->mi_flags |= MI_ASYNC_MGR_STOP;
+ mi->mi_flags |= (MI_ASYNC_MGR_STOP|MI_DEAD);
mutex_exit(&mi->mi_lock);
/*
* Wake up the async manager thread.
*/
cv_broadcast(&mi->mi_async_reqs_cv);
mutex_exit(&mi->mi_async_lock);
+
+ /*
+ * Drop lock and release FS, which may change list, then repeat.
+ * We're done when every mi has been done or the list is empty.
+ */
+ mutex_exit(&mig->mig_lock);
+ VFS_RELE(mi->mi_vfsp);
+ goto again;
}
mutex_exit(&mig->mig_lock);
}
diff --git a/usr/src/uts/common/nfs/nfs4_clnt.h b/usr/src/uts/common/nfs/nfs4_clnt.h
index 0d0a4d6ed0..6eab1695ef 100644
--- a/usr/src/uts/common/nfs/nfs4_clnt.h
+++ b/usr/src/uts/common/nfs/nfs4_clnt.h
@@ -1038,7 +1038,7 @@ typedef struct mntinfo4 {
* MI4_MOUNTING mount in progress, don't failover
* MI4_POSIX_LOCK if server is using POSIX locking
* MI4_LOCK_DEBUG cmn_err'd posix lock err msg
- * MI4_DEAD last VFS_RELE() called on mount
+ * MI4_DEAD mount has been terminated
* MI4_INACTIVE_IDLE inactive thread idle
* MI4_BADOWNER_DEBUG badowner error msg per mount
* MI4_ASYNC_MGR_STOP tell async manager to die
diff --git a/usr/src/uts/common/nfs/nfs_clnt.h b/usr/src/uts/common/nfs/nfs_clnt.h
index 948c9a06b0..fad7d4aa0f 100644
--- a/usr/src/uts/common/nfs/nfs_clnt.h
+++ b/usr/src/uts/common/nfs/nfs_clnt.h
@@ -423,6 +423,7 @@ typedef struct mntinfo {
#define MI_DIRECTIO 0x40000 /* do direct I/O */
#define MI_EXTATTR 0x80000 /* server supports extended attrs */
#define MI_ASYNC_MGR_STOP 0x100000 /* tell async mgr to die */
+#define MI_DEAD 0x200000 /* mount has been terminated */
/*
* Read-only mntinfo statistics