Index: sys/ufs/ffs/ffs_vfsops.c =================================================================== --- sys/ufs/ffs/ffs_vfsops.c +++ sys/ufs/ffs/ffs_vfsops.c @@ -461,6 +461,29 @@ mp->mnt_kern_flag &= ~MNTK_FPLOOKUP; mp->mnt_flag |= mntorflags; MNT_IUNLOCK(mp); + /* + * Must not call namei() while owning busy ref. + */ + if ((mp->mnt_flag & MNT_UPDATE) != 0) + vfs_unbusy(mp); + /* + * Not an update, or updating the name: look up the name + * and verify that it refers to a sensible disk device. + */ + NDINIT(&ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, td); + error = namei(&ndp); + if ((mp->mnt_flag & MNT_UPDATE) != 0) { + /* + * Unmount does not start if MNT_UPDATE is set. Mount + * update busies mp before setting MNT_UPDATE. We + * must be able to retain our busy ref successfully, + * without sleep. + */ + error1 = vfs_busy(mp, MBF_NOWAIT); + MPASS(error1 == 0); + } + error1 = error; + /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. @@ -567,7 +590,7 @@ if ((mp->mnt_flag & MNT_RELOAD) && (error = ffs_reload(mp, td, 0)) != 0) return (error); - if (fs->fs_ronly && + if (fs->fs_ronly && error1 == 0 && !vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) { /* * If we are running a checker, do not allow upgrade. @@ -725,33 +748,14 @@ */ if (mp->mnt_flag & MNT_SNAPSHOT) return (ffs_snapshot(mp, fspec)); - - /* - * Must not call namei() while owning busy ref. - */ - vfs_unbusy(mp); } - /* - * Not an update, or updating the name: look up the name - * and verify that it refers to a sensible disk device. - */ - NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td); - error = namei(&ndp); - if ((mp->mnt_flag & MNT_UPDATE) != 0) { - /* - * Unmount does not start if MNT_UPDATE is set. Mount - * update busies mp before setting MNT_UPDATE. We - * must be able to retain our busy ref succesfully, - * without sleep. - */ - error1 = vfs_busy(mp, MBF_NOWAIT); - MPASS(error1 == 0); - } - if (error != 0) - return (error); + if (error1 != 0) + return (error1); NDFREE(&ndp, NDF_ONLY_PNBUF); devvp = ndp.ni_vp; + if ((error = vget(devvp, LK_EXCLUSIVE | LK_RETRY)) != 0) + return (error); if (!vn_isdisk_error(devvp, &error)) { vput(devvp); return (error);