Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 Aug 2018 19:06:55 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r337055 - head/sys/ufs/ffs
Message-ID:  <201808011906.w71J6tBe032796@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Aug  1 19:06:55 2018
New Revision: 337055
URL: https://svnweb.freebsd.org/changeset/base/337055

Log:
  Avoid assertion in /dev/ufssuspend when the suspend ioctl is
  (incorrectly) called while another suspension is already active.
  
  PR:	230220
  Reported by:	dexuan
  Tested by:	pho
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week

Modified:
  head/sys/ufs/ffs/ffs_suspend.c

Modified: head/sys/ufs/ffs/ffs_suspend.c
==============================================================================
--- head/sys/ufs/ffs/ffs_suspend.c	Wed Aug  1 19:02:05 2018	(r337054)
+++ head/sys/ufs/ffs/ffs_suspend.c	Wed Aug  1 19:06:55 2018	(r337055)
@@ -218,6 +218,33 @@ ffs_susp_suspend(struct mount *mp)
 }
 
 static void
+ffs_susp_unsuspend(struct mount *mp)
+{
+	struct ufsmount *ump;
+
+	sx_assert(&ffs_susp_lock, SA_XLOCKED);
+
+	/*
+	 * XXX: The status is kept per-process; the vfs_write_resume() routine
+	 * 	asserts that the resuming thread is the same one that called
+	 * 	vfs_write_suspend().  The cdevpriv data, however, is attached
+	 * 	to the file descriptor, e.g. is inherited during fork.  Thus,
+	 * 	it's possible that the resuming process will be different from
+	 * 	the one that started the suspension.
+	 *
+	 * 	Work around by fooling the check in vfs_write_resume().
+	 */
+	mp->mnt_susp_owner = curthread;
+
+	vfs_write_resume(mp, 0);
+	ump = VFSTOUFS(mp);
+	UFS_LOCK(ump);
+	ump->um_flags &= ~UM_WRITESUSPENDED;
+	UFS_UNLOCK(ump);
+	vfs_unbusy(mp);
+}
+
+static void
 ffs_susp_dtor(void *data)
 {
 	struct fs *fs;
@@ -243,24 +270,7 @@ ffs_susp_dtor(void *data)
 	if (error != 0)
 		panic("failed to unsuspend writes on %s", fs->fs_fsmnt);
 
-	/*
-	 * XXX: The status is kept per-process; the vfs_write_resume() routine
-	 * 	asserts that the resuming thread is the same one that called
-	 * 	vfs_write_suspend().  The cdevpriv data, however, is attached
-	 * 	to the file descriptor, e.g. is inherited during fork.  Thus,
-	 * 	it's possible that the resuming process will be different from
-	 * 	the one that started the suspension.
-	 *
-	 * 	Work around by fooling the check in vfs_write_resume().
-	 */
-	mp->mnt_susp_owner = curthread;
-
-	vfs_write_resume(mp, 0);
-	vfs_unbusy(mp);
-	UFS_LOCK(ump);
-	ump->um_flags &= ~UM_WRITESUSPENDED;
-	UFS_UNLOCK(ump);
-
+	ffs_susp_unsuspend(mp);
 	sx_xunlock(&ffs_susp_lock);
 }
 
@@ -300,7 +310,8 @@ ffs_susp_ioctl(struct cdev *dev, u_long cmd, caddr_t a
 			break;
 		}
 		error = devfs_set_cdevpriv(mp, ffs_susp_dtor);
-		KASSERT(error == 0, ("devfs_set_cdevpriv failed"));
+		if (error != 0)
+			ffs_susp_unsuspend(mp);
 		break;
 	case UFSRESUME:
 		error = devfs_get_cdevpriv((void **)&mp);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201808011906.w71J6tBe032796>