aboutsummaryrefslogtreecommitdiff
path: root/sys/ufs/ffs/ffs_suspend.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ufs/ffs/ffs_suspend.c')
-rw-r--r--sys/ufs/ffs/ffs_suspend.c49
1 files changed, 30 insertions, 19 deletions
diff --git a/sys/ufs/ffs/ffs_suspend.c b/sys/ufs/ffs/ffs_suspend.c
index 153f726a5ae9..b8ad1e7696b4 100644
--- a/sys/ufs/ffs/ffs_suspend.c
+++ b/sys/ufs/ffs/ffs_suspend.c
@@ -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 addr, int flags,
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);