Skip site navigation (1)Skip section navigation (2)
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>