summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_subr.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2018-02-10 05:24:24 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2018-02-10 05:24:24 +0000
commit46a5fdccdbec824aec3e3e383277baed4c200dee (patch)
treed5edda8fa947c8eeb74eb1c49f6b40b68b93b101 /sys/kern/vfs_subr.c
parentd02979485b47a573dd086a214bbd30bce63e5708 (diff)
Syncronize filesystems to disk when suspending. Each mountpoint's vnodes
are pushed to disk. Dangling vnodes (unlinked files still in use) and vnodes undergoing change by long-running syscalls are identified -- and such filesystems are marked dirty on-disk while we are suspended (in case power is lost, a fsck will be required). Filesystems without dangling or busy vnodes are marked clean, resulting in faster boots following "battery died" circumstances. Tested by numerous developers, thanks for the feedback.
Diffstat (limited to 'sys/kern/vfs_subr.c')
-rw-r--r--sys/kern/vfs_subr.c57
1 files changed, 49 insertions, 8 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 7311916fbf5..1e325fa3eca 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_subr.c,v 1.265 2017/12/14 20:23:15 deraadt Exp $ */
+/* $OpenBSD: vfs_subr.c,v 1.266 2018/02/10 05:24:23 deraadt Exp $ */
/* $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $ */
/*
@@ -72,7 +72,7 @@
#include "softraid.h"
-void sr_shutdown(int);
+void sr_quiesce(void);
enum vtype iftovt_tab[16] = {
VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
@@ -1583,6 +1583,48 @@ vaccess(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid,
return (file_mode & mask) == mask ? 0 : EACCES;
}
+struct rwlock vfs_stall_lock = RWLOCK_INITIALIZER("vfs_stall");
+
+int
+vfs_stall(struct proc *p, int stall)
+{
+ struct mount *mp, *nmp;
+ int allerror = 0, error;
+
+ if (stall)
+ rw_enter_write(&vfs_stall_lock);
+
+ TAILQ_FOREACH_REVERSE_SAFE(mp, &mountlist, mntlist, mnt_list, nmp) {
+ if (stall) {
+ error = vfs_busy(mp, VB_WRITE|VB_WAIT);
+ if (error) {
+ printf("%s: busy\n", mp->mnt_stat.f_mntonname);
+ allerror = error;
+ continue;
+ }
+ uvm_vnp_sync(mp);
+ error = VFS_SYNC(mp, MNT_WAIT, stall, p->p_ucred, p);
+ if (error) {
+ printf("%s: failed to sync\n", mp->mnt_stat.f_mntonname);
+ vfs_unbusy(mp);
+ allerror = error;
+ continue;
+ }
+ mp->mnt_flag |= MNT_STALLED;
+ } else {
+ if (mp->mnt_flag & MNT_STALLED) {
+ vfs_unbusy(mp);
+ mp->mnt_flag &= ~MNT_STALLED;
+ }
+ }
+ }
+
+ if (!stall)
+ rw_exit_write(&vfs_stall_lock);
+
+ return (allerror);
+}
+
int
vfs_readonly(struct mount *mp, struct proc *p)
{
@@ -1594,7 +1636,7 @@ vfs_readonly(struct mount *mp, struct proc *p)
return (error);
}
uvm_vnp_sync(mp);
- error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p);
+ error = VFS_SYNC(mp, MNT_WAIT, 0, p->p_ucred, p);
if (error) {
printf("%s: failed to sync\n", mp->mnt_stat.f_mntonname);
vfs_unbusy(mp);
@@ -1628,7 +1670,6 @@ vfs_rofs(struct proc *p)
struct mount *mp, *nmp;
TAILQ_FOREACH_REVERSE_SAFE(mp, &mountlist, mntlist, mnt_list, nmp) {
- /* XXX Here is a race, the next pointer is not locked. */
(void) vfs_readonly(mp, p);
}
}
@@ -1651,14 +1692,14 @@ vfs_shutdown(struct proc *p)
vfs_rofs(p);
}
+#if NSOFTRAID > 0
+ sr_quiesce();
+#endif
+
if (vfs_syncwait(p, 1))
printf("giving up\n");
else
printf("done\n");
-
-#if NSOFTRAID > 0
- sr_shutdown(1);
-#endif
}
/*