svn commit: r188623 - in stable/7/sys: . contrib/pf dev/ath/ath_hal
dev/cxgb ufs/ffs
Konstantin Belousov
kib at FreeBSD.org
Sat Feb 14 15:22:40 PST 2009
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);
}
/*
More information about the svn-src-all
mailing list