Mercurial > illumos > illumos-gate
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.