changeset 12895:5c6de9ad51b9

6962062 recurring bad pointer panic in autofs:unmount_subtree
author Jan Kryl <Jan.Kryl@Sun.COM>
date Wed, 21 Jul 2010 17:59:37 +0200
parents 5213e1b8c605
children 8ed2c2ace7da
files usr/src/uts/common/fs/autofs/auto_subr.c usr/src/uts/common/sys/fs/autofs.h
diffstat 2 files changed, 24 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/autofs/auto_subr.c	Wed Jul 21 14:36:46 2010 +0100
+++ b/usr/src/uts/common/fs/autofs/auto_subr.c	Wed Jul 21 17:59:37 2010 +0200
@@ -2359,6 +2359,28 @@
 		 */
 		if (currfnp->fn_unmount_ref_time < timestamp)
 			currfnp->fn_unmount_ref_time = timestamp;
+
+		/*
+		 * Don't descent below nodes, which are being unmounted/mounted.
+		 *
+		 * We need to hold both locks at once: fn_lock because we need
+		 * to read MF_INPROG and fn_rwlock to prevent anybody from
+		 * modifying fn_trigger until its used to traverse triggers
+		 * below.
+		 *
+		 * Acquire fn_rwlock in non-blocking mode to avoid deadlock.
+		 * If it can't be acquired, then acquire locks in correct
+		 * order.
+		 */
+		if (!rw_tryenter(&currfnp->fn_rwlock, RW_READER)) {
+			mutex_exit(&currfnp->fn_lock);
+			rw_enter(&currfnp->fn_rwlock, RW_READER);
+			mutex_enter(&currfnp->fn_lock);
+		}
+		if (currfnp->fn_flags & MF_INPROG) {
+			rw_exit(&currfnp->fn_rwlock);
+			continue;
+		}
 		mutex_exit(&currfnp->fn_lock);
 
 		/*
@@ -2366,7 +2388,6 @@
 		 * mounts.
 		 */
 
-		rw_enter(&currfnp->fn_rwlock, RW_READER);
 		if ((nextfnp = currfnp->fn_trigger) != NULL) {
 			VN_HOLD(fntovn(nextfnp));
 			rw_exit(&currfnp->fn_rwlock);
--- a/usr/src/uts/common/sys/fs/autofs.h	Wed Jul 21 14:36:46 2010 +0100
+++ b/usr/src/uts/common/sys/fs/autofs.h	Wed Jul 21 17:59:37 2010 +0200
@@ -107,6 +107,8 @@
  *                 - Grab writers to add a new fnnode under fn_dirents and
  *		     to remove a node pointed to by fn_dirents or fn_next.
  *
+ *	Lock ordering:
+ *		fn_rwlock > fn_lock
  *
  * The flags:
  *	MF_INPROG: