changeset 9736:4958b6b7822d

6818559 deadlock between acct_find()/ufs_check_lockfs() if process accounting enabled when lockfs -w /var
author batschul
date Wed, 27 May 2009 08:27:53 -0600
parents 0e6bec37f788
children f100be4364e0
files usr/src/uts/common/fs/ufs/ufs_lockfs.c
diffstat 1 files changed, 20 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/ufs/ufs_lockfs.c	Wed May 27 12:08:46 2009 +0530
+++ b/usr/src/uts/common/fs/ufs/ufs_lockfs.c	Wed May 27 08:27:53 2009 -0600
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/t_lock.h>
 #include <sys/param.h>
@@ -885,20 +883,33 @@
 	if (!vp || !vp->v_vfsp || !vp->v_vfsp->vfs_data)
 		return (EIO);
 
-	if (vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) /* has been unmounted */
+	vfsp = vp->v_vfsp;
+
+	if (vfsp->vfs_flag & VFS_UNMOUNTED) /* has been unmounted */
 		return (EIO);
 
 	/* take the lock and check again */
-	vfs_lock_wait(vp->v_vfsp);
-	if (vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) {
-		vfs_unlock(vp->v_vfsp);
+	vfs_lock_wait(vfsp);
+	if (vfsp->vfs_flag & VFS_UNMOUNTED) {
+		vfs_unlock(vfsp);
 		return (EIO);
 	}
 
-	vfsp = vp->v_vfsp;
+	/*
+	 * Can't wlock or ro/elock fs with accounting or local swap file
+	 * We need to check for this before we grab the ul_lock to avoid
+	 * deadlocks with the accounting framework.
+	 */
+	if ((LOCKFS_IS_WLOCK(lockfsp) || LOCKFS_IS_ELOCK(lockfsp) ||
+	    LOCKFS_IS_ROELOCK(lockfsp)) && !from_log) {
+		if (ufs_checkaccton(vp) || ufs_checkswapon(vp)) {
+			vfs_unlock(vfsp);
+			return (EDEADLK);
+		}
+	}
+
 	ufsvfsp = (struct ufsvfs *)vfsp->vfs_data;
 	ulp = &ufsvfsp->vfs_ulockfs;
-
 	head = (ulockfs_info_t *)tsd_get(ufs_lockfs_key);
 	SEARCH_ULOCKFSP(head, ulp, info);
 
@@ -1029,17 +1040,6 @@
 	}
 
 	/*
-	 * can't wlock or (ro)elock fs with accounting or local swap file
-	 */
-	if ((ULOCKFS_IS_WLOCK(ulp) || ULOCKFS_IS_ELOCK(ulp) ||
-	    ULOCKFS_IS_ROELOCK(ulp)) && !from_log) {
-		if (error = ufs_checkaccton(vp))
-			goto errout;
-		if (error = ufs_checkswapon(vp))
-			goto errout;
-	}
-
-	/*
 	 * save error lock status to pass down to reconcilation
 	 * routines and for later cleanup
 	 */