Date: Sat, 14 Feb 2009 23:22:38 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org Subject: svn commit: r188623 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb ufs/ffs Message-ID: <200902142322.n1ENMcpo033268@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Sat Feb 14 23:22:37 2009 New Revision: 188623 URL: http://svn.freebsd.org/changeset/base/188623 Log: MFC r183074: Suspend the write operations on the UFS filesystem being unmounted or remounted from rw to ro. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/ufs/ffs/ffs_vfsops.c Modified: stable/7/sys/ufs/ffs/ffs_vfsops.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 23:20:00 2009 (r188622) +++ stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 23:22:37 2009 (r188623) @@ -189,14 +189,35 @@ ffs_mount(struct mount *mp, struct threa devvp = ump->um_devvp; if (fs->fs_ronly == 0 && vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) { - if ((error = vn_start_write(NULL, &mp, V_WAIT)) != 0) - return (error); /* - * Flush any dirty data. + * Flush any dirty data and suspend filesystem. */ - if ((error = ffs_sync(mp, MNT_WAIT, td)) != 0) { - vn_finished_write(mp); + if ((error = vn_start_write(NULL, &mp, V_WAIT)) != 0) return (error); + for (;;) { + vn_finished_write(mp); + if ((error = vfs_write_suspend(mp)) != 0) + return (error); + MNT_ILOCK(mp); + if (mp->mnt_kern_flag & MNTK_SUSPENDED) { + /* + * Allow the secondary writes + * to proceed. + */ + mp->mnt_kern_flag &= ~(MNTK_SUSPENDED | + MNTK_SUSPEND2); + wakeup(&mp->mnt_flag); + MNT_IUNLOCK(mp); + /* + * Allow the curthread to + * ignore the suspension to + * synchronize on-disk state. + */ + curthread->td_pflags |= TDP_IGNSUSP; + break; + } + MNT_IUNLOCK(mp); + vn_start_write(NULL, &mp, V_WAIT); } /* * Check for and optionally get rid of files open @@ -211,7 +232,7 @@ ffs_mount(struct mount *mp, struct threa error = ffs_flushfiles(mp, flags, td); } if (error) { - vn_finished_write(mp); + vfs_write_resume(mp); return (error); } if (fs->fs_pendingblocks != 0 || @@ -228,10 +249,9 @@ ffs_mount(struct mount *mp, struct threa if ((error = ffs_sbupdate(ump, MNT_WAIT, 0)) != 0) { fs->fs_ronly = 0; fs->fs_clean = 0; - vn_finished_write(mp); + vfs_write_resume(mp); return (error); } - vn_finished_write(mp); DROP_GIANT(); g_topology_lock(); g_access(ump->um_cp, 0, -1, 0); @@ -241,6 +261,11 @@ ffs_mount(struct mount *mp, struct threa MNT_ILOCK(mp); mp->mnt_flag |= MNT_RDONLY; MNT_IUNLOCK(mp); + /* + * Allow the writers to note that filesystem + * is ro now. + */ + vfs_write_resume(mp); } if ((mp->mnt_flag & MNT_RELOAD) && (error = ffs_reload(mp, td)) != 0) @@ -1004,12 +1029,15 @@ ffs_unmount(mp, mntflags, td) { struct ufsmount *ump = VFSTOUFS(mp); struct fs *fs; - int error, flags; + int error, flags, susp; flags = 0; + fs = ump->um_fs; if (mntflags & MNT_FORCE) { flags |= FORCECLOSE; - } + susp = fs->fs_ronly != 0; + } else + susp = 0; #ifdef UFS_EXTATTR if ((error = ufs_extattr_stop(mp, td))) { if (error != EOPNOTSUPP) @@ -1019,14 +1047,34 @@ ffs_unmount(mp, mntflags, td) ufs_extattr_uepm_destroy(&ump->um_extattr); } #endif + if (susp) { + /* + * dounmount already called vn_start_write(). + */ + for (;;) { + vn_finished_write(mp); + if ((error = vfs_write_suspend(mp)) != 0) + return (error); + MNT_ILOCK(mp); + if (mp->mnt_kern_flag & MNTK_SUSPENDED) { + mp->mnt_kern_flag &= ~(MNTK_SUSPENDED | + MNTK_SUSPEND2); + wakeup(&mp->mnt_flag); + MNT_IUNLOCK(mp); + curthread->td_pflags |= TDP_IGNSUSP; + break; + } + MNT_IUNLOCK(mp); + vn_start_write(NULL, &mp, V_WAIT); + } + } if (mp->mnt_flag & MNT_SOFTDEP) { if ((error = softdep_flushfiles(mp, flags, td)) != 0) - return (error); + goto fail; } else { if ((error = ffs_flushfiles(mp, flags, td)) != 0) - return (error); + goto fail; } - fs = ump->um_fs; UFS_LOCK(ump); if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) { printf("%s: unmount pending error: blocks %jd files %d\n", @@ -1041,9 +1089,13 @@ ffs_unmount(mp, mntflags, td) error = ffs_sbupdate(ump, MNT_WAIT, 0); if (error) { fs->fs_clean = 0; - return (error); + goto fail; } } + if (susp) { + vfs_write_resume(mp); + vn_start_write(NULL, &mp, V_WAIT); + } DROP_GIANT(); g_topology_lock(); g_vfs_close(ump->um_cp, td); @@ -1063,6 +1115,13 @@ ffs_unmount(mp, mntflags, td) mp->mnt_flag &= ~MNT_LOCAL; MNT_IUNLOCK(mp); return (error); + +fail: + if (susp) { + vfs_write_resume(mp); + vn_start_write(NULL, &mp, V_WAIT); + } + return (error); } /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902142322.n1ENMcpo033268>