Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Aug 2018 18:51:39 +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-11@freebsd.org
Subject:   svn commit: r337483 - stable/11/sys/ufs/ffs
Message-ID:  <201808081851.w78IpdXh043540@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Aug  8 18:51:39 2018
New Revision: 337483
URL: https://svnweb.freebsd.org/changeset/base/337483

Log:
  MFC r337055:
  Avoid assertion in /dev/ufssuspend when the suspend ioctl is
  (incorrectly) called while another suspension is already active.
  
  PR:	230220

Modified:
  stable/11/sys/ufs/ffs/ffs_suspend.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/ufs/ffs/ffs_suspend.c
==============================================================================
--- stable/11/sys/ufs/ffs/ffs_suspend.c	Wed Aug  8 18:50:42 2018	(r337482)
+++ stable/11/sys/ufs/ffs/ffs_suspend.c	Wed Aug  8 18:51:39 2018	(r337483)
@@ -214,6 +214,31 @@ 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);
+	ump->um_writesuspended = 0;
+	vfs_unbusy(mp);
+}
+
+static void
 ffs_susp_dtor(void *data)
 {
 	struct fs *fs;
@@ -239,22 +264,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);
-	ump->um_writesuspended = 0;
-
+	ffs_susp_unsuspend(mp);
 	sx_xunlock(&ffs_susp_lock);
 }
 
@@ -294,7 +304,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?201808081851.w78IpdXh043540>