svn commit: r337055 - head/sys/ufs/ffs
Konstantin Belousov
kib at FreeBSD.org
Wed Aug 1 19:06:56 UTC 2018
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);
More information about the svn-src-all
mailing list