diff options
author | thurlow <none@none> | 2005-07-29 16:17:08 -0700 |
---|---|---|
committer | thurlow <none@none> | 2005-07-29 16:17:08 -0700 |
commit | 3fd6cc295d1c8c721b4b8abb49bbe0fefe51d034 (patch) | |
tree | b5473bf5a24b74a6db9fd957ecc27099df913854 /usr/src | |
parent | 0ab54cfb0b7bb7b02cb898cc6c9f6a36237410c4 (diff) | |
download | illumos-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.c | 21 | ||||
-rw-r--r-- | usr/src/uts/common/fs/nfs/nfs_client.c | 25 | ||||
-rw-r--r-- | usr/src/uts/common/nfs/nfs4_clnt.h | 2 | ||||
-rw-r--r-- | usr/src/uts/common/nfs/nfs_clnt.h | 1 |
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 |