changeset 921:1bb512d7785a

6280143 lufs_enable() strikes again 6215065 Booting off single disk from mirrored root pair causes panic reset
author batschul
date Tue, 15 Nov 2005 01:52:32 -0800
parents 5061227f5943
children f5c8f1a2c9e3
files usr/src/uts/common/fs/ufs/lufs.c usr/src/uts/common/fs/ufs/ufs_lockfs.c usr/src/uts/common/fs/ufs/ufs_vfsops.c
diffstat 3 files changed, 80 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/ufs/lufs.c	Mon Nov 14 22:43:41 2005 -0800
+++ b/usr/src/uts/common/fs/ufs/lufs.c	Tue Nov 15 01:52:32 2005 -0800
@@ -50,6 +50,8 @@
 #include <sys/kstat.h>
 #include <sys/cmn_err.h>
 
+extern	kmutex_t	ufs_scan_lock;
+
 static kmutex_t	log_mutex;	/* general purpose log layer lock */
 kmutex_t	ml_scan;	/* Scan thread syncronization */
 kcondvar_t	ml_scan_cv;	/* Scan thread syncronization */
@@ -384,10 +386,19 @@
 		ul->un_matamap = map_get(ul, matamaptype, DELTAMAP_NHASH);
 	mutex_init(&ul->un_log_mutex, NULL, MUTEX_DEFAULT, NULL);
 	mutex_init(&ul->un_state_mutex, NULL, MUTEX_DEFAULT, NULL);
+
+	/*
+	 * Aquire the ufs_scan_lock before linking the mtm data
+	 * structure so that we keep ufs_sync() and ufs_update() away
+	 * when they execute the ufs_scan_inodes() run while we're in
+	 * progress of enabling/disabling logging.
+	 */
+	mutex_enter(&ufs_scan_lock);
 	ufsvfsp->vfs_log = ul;
 
 	/* remember the state of the log before the log scan */
 	logmap_logscan(ul);
+	mutex_exit(&ufs_scan_lock);
 
 	/*
 	 * Error during scan
@@ -398,7 +409,16 @@
 	 */
 	if (ul->un_flags & LDL_ERROR) {
 		if (!ronly) {
+			/*
+			 * Aquire the ufs_scan_lock before de-linking
+			 * the mtm data structure so that we keep ufs_sync()
+			 * and ufs_update() away when they execute the
+			 * ufs_scan_inodes() run while we're in progress of
+			 * enabling/disabling logging.
+			 */
+			mutex_enter(&ufs_scan_lock);
 			lufs_unsnarf(ufsvfsp);
+			mutex_exit(&ufs_scan_lock);
 			return (EIO);
 		}
 		ul->un_flags &= ~LDL_ERROR;
@@ -840,8 +860,14 @@
 
 	/*
 	 * Free all of the incore structs
+	 * Aquire the ufs_scan_lock before de-linking the mtm data
+	 * structure so that we keep ufs_sync() and ufs_update() away
+	 * when they execute the ufs_scan_inodes() run while we're in
+	 * progress of enabling/disabling logging.
 	 */
+	mutex_enter(&ufs_scan_lock);
 	(void) lufs_unsnarf(ufsvfsp);
+	mutex_exit(&ufs_scan_lock);
 
 	atomic_add_long(&ufs_quiesce_pend, -1);
 	mutex_exit(&ulp->ul_lock);
@@ -964,6 +990,14 @@
 	}
 
 	/*
+	 * Grab appropriate locks to synchronize with the rest
+	 * of the system
+	 */
+	vfs_lock_wait(vfsp);
+	ulp = &ufsvfsp->vfs_ulockfs;
+	mutex_enter(&ulp->ul_lock);
+
+	/*
 	 * File system must be fairly consistent to enable logging
 	 */
 	if (fs->fs_clean != FSLOG &&
@@ -994,6 +1028,9 @@
 		 * this point.  Disabling sets fs->fs_logbno to 0, so this
 		 * will not put us into an infinite loop.
 		 */
+		mutex_exit(&ulp->ul_lock);
+		vfs_unlock(vfsp);
+
 		lf.lf_lock = LOCKFS_ULOCK;
 		lf.lf_flags = 0;
 		error = ufs_fiolfs(vp, &lf, 1);
@@ -1024,19 +1061,12 @@
 
 	/*
 	 * Pretend we were just mounted with logging enabled
-	 *	freeze and drain the file system of readers
 	 *		Get the ops vector
 	 *		If debug, record metadata locations with log subsystem
 	 *		Start the delete thread
 	 *		Start the reclaim thread, if necessary
-	 *	Thaw readers
 	 */
-	vfs_lock_wait(vfsp);
 	vfs_setmntopt(vfsp, MNTOPT_LOGGING, NULL, 0);
-	ulp = &ufsvfsp->vfs_ulockfs;
-	mutex_enter(&ulp->ul_lock);
-	atomic_add_long(&ufs_quiesce_pend, 1);
-	(void) ufs_quiesce(ulp);
 
 	TRANS_DOMATAMAP(ufsvfsp);
 	TRANS_MATA_MOUNT(ufsvfsp);
@@ -1050,7 +1080,6 @@
 	} else
 		fs->fs_reclaim |= reclaim;
 
-	atomic_add_long(&ufs_quiesce_pend, -1);
 	mutex_exit(&ulp->ul_lock);
 	vfs_unlock(vfsp);
 
@@ -1080,9 +1109,21 @@
 	return (0);
 
 errout:
+	/*
+	 * Aquire the ufs_scan_lock before de-linking the mtm data
+	 * structure so that we keep ufs_sync() and ufs_update() away
+	 * when they execute the ufs_scan_inodes() run while we're in
+	 * progress of enabling/disabling logging.
+	 */
+	mutex_enter(&ufs_scan_lock);
 	(void) lufs_unsnarf(ufsvfsp);
+	mutex_exit(&ufs_scan_lock);
+
 	(void) lufs_free(ufsvfsp);
 unlockout:
+	mutex_exit(&ulp->ul_lock);
+	vfs_unlock(vfsp);
+
 	lf.lf_lock = LOCKFS_ULOCK;
 	lf.lf_flags = 0;
 	(void) ufs_fiolfs(vp, &lf, 1);
--- a/usr/src/uts/common/fs/ufs/ufs_lockfs.c	Mon Nov 14 22:43:41 2005 -0800
+++ b/usr/src/uts/common/fs/ufs/ufs_lockfs.c	Tue Nov 15 01:52:32 2005 -0800
@@ -367,19 +367,32 @@
 		ufs_checkclean(vfsp);
 
 	/*
-	 * flush any outstanding transactions and roll the log
+	 * Flush any outstanding transactions and roll the log
+	 * only if we are supposed to do, i.e. LDL_NOROLL not set.
+	 * We can not simply check for fs_ronly here since fsck also may
+	 * use this code to roll the log on a read-only filesystem, e.g.
+	 * root during early stages of boot, if other then a sanity check is
+	 * done, it will clear LDL_NOROLL before.
+	 * In addition we assert that the deltamap does not contain any deltas
+	 * in case LDL_NOROLL is set since this is not supposed to happen.
 	 */
 	if (TRANS_ISTRANS(ufsvfsp)) {
-		curthread->t_flag |= T_DONTBLOCK;
-		TRANS_BEGIN_SYNC(ufsvfsp, TOP_COMMIT_FLUSH, TOP_COMMIT_SIZE,
-		    error);
-		if (!error) {
-			TRANS_END_SYNC(ufsvfsp, saverror, TOP_COMMIT_FLUSH,
-			    TOP_COMMIT_SIZE);
+		ml_unit_t	*ul	= ufsvfsp->vfs_log;
+		mt_map_t	*mtm	= ul->un_deltamap;
+
+		if (ul->un_flags & LDL_NOROLL) {
+			ASSERT(mtm->mtm_nme == 0);
+		} else {
+			curthread->t_flag |= T_DONTBLOCK;
+			TRANS_BEGIN_SYNC(ufsvfsp, TOP_COMMIT_FLUSH,
+			    TOP_COMMIT_SIZE, error);
+			if (!error) {
+				TRANS_END_SYNC(ufsvfsp, saverror,
+				    TOP_COMMIT_FLUSH, TOP_COMMIT_SIZE);
+			}
+			curthread->t_flag &= ~T_DONTBLOCK;
+			logmap_roll_dev(ufsvfsp->vfs_log);
 		}
-		curthread->t_flag &= ~T_DONTBLOCK;
-
-		logmap_roll_dev(ufsvfsp->vfs_log); /* fully roll the log */
 	}
 
 	return (saverror);
--- a/usr/src/uts/common/fs/ufs/ufs_vfsops.c	Mon Nov 14 22:43:41 2005 -0800
+++ b/usr/src/uts/common/fs/ufs/ufs_vfsops.c	Tue Nov 15 01:52:32 2005 -0800
@@ -618,24 +618,12 @@
 		goto remounterr;
 
 	/*
-	 * Lock the file system and flush stuff from memory
+	 * quiesce the file system
 	 */
 	error = ufs_quiesce(ulp);
 	if (error)
 		goto remounterr;
 
-	/*
-	 * We don't need to call the expensive ufs_flush when going from
-	 * read only to read/write, except if the root fs didn't come
-	 * down cleanly.
-	 */
-	if ((ufsvfsp->vfs_devvp == rootvp) && !ufs_clean_root) {
-		error = ufs_flush(vfsp);
-		if (error) {
-			goto remounterr;
-		}
-	}
-
 	tpt = UFS_BREAD(ufsvfsp, ufsvfsp->vfs_dev, SBLOCK, SBSIZE);
 	if (tpt->b_flags & B_ERROR) {
 		error = EIO;
@@ -2196,15 +2184,16 @@
 
 		/*
 		 * Clear the noroll bit which indicates that logging
-		 * can't roll the log yet.
+		 * can't roll the log yet and start the logmap roll thread
+		 * unless the filesystem is still read-only in which case
+		 * remountfs() will do it when going to read-write.
 		 */
 		ASSERT(ul->un_flags & LDL_NOROLL);
-		ul->un_flags &= ~LDL_NOROLL;
 
-		/*
-		 * Start the logmap roll thread.
-		 */
-		logmap_start_roll(ul);
+		if (!fsp->fs_ronly) {
+			ul->un_flags &= ~LDL_NOROLL;
+			logmap_start_roll(ul);
+		}
 
 		/*
 		 * Start the reclaim thread if needed.