summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbluhm <bluhm@openbsd.org>2018-03-07 18:30:23 +0000
committerbluhm <bluhm@openbsd.org>2018-03-07 18:30:23 +0000
commitf7fa0173b23753cbd73c4976a9e26daef8e82cad (patch)
tree7d116834d777cf85db878c1bf89f0c547753a9d5
parentRFC 7136 clarifies that the "u" and "g" bits are only significant when (diff)
downloadwireguard-openbsd-f7fa0173b23753cbd73c4976a9e26daef8e82cad.tar.xz
wireguard-openbsd-f7fa0173b23753cbd73c4976a9e26daef8e82cad.zip
Remounting files systems read-only does not work reliably. There
are corner cases where ffs may leak blocks. So better revert and unmount all file systems at reboot. The "init died" panic will be fixed in a different way. OK deraadt@
-rw-r--r--sys/kern/vfs_subr.c67
1 files changed, 27 insertions, 40 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 1e325fa3eca..72ce218967b 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_subr.c,v 1.266 2018/02/10 05:24:23 deraadt Exp $ */
+/* $OpenBSD: vfs_subr.c,v 1.267 2018/03/07 18:30:23 bluhm Exp $ */
/* $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $ */
/*
@@ -115,6 +115,8 @@ void vputonfreelist(struct vnode *);
int vflush_vnode(struct vnode *, void *);
int maxvnodes;
+void vfs_unmountall(void);
+
#ifdef DEBUG
void printlockedvnodes(void);
#endif
@@ -1625,52 +1627,37 @@ vfs_stall(struct proc *p, int stall)
return (allerror);
}
-int
-vfs_readonly(struct mount *mp, struct proc *p)
-{
- int error;
-
- error = vfs_busy(mp, VB_WRITE|VB_WAIT);
- if (error) {
- printf("%s: busy\n", mp->mnt_stat.f_mntonname);
- return (error);
- }
- uvm_vnp_sync(mp);
- 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);
- return (error);
- }
-
- mp->mnt_flag |= MNT_UPDATE | MNT_RDONLY;
- mp->mnt_flag &= ~MNT_SOFTDEP;
- error = VFS_MOUNT(mp, mp->mnt_stat.f_mntonname, NULL, NULL, curproc);
- if (error) {
- printf("%s: failed to remount rdonly, error %d\n",
- mp->mnt_stat.f_mntonname, error);
- vfs_unbusy(mp);
- return (error);
- }
- if (mp->mnt_syncer != NULL)
- vgone(mp->mnt_syncer);
- mp->mnt_syncer = NULL;
- vfs_unbusy(mp);
- return (error);
-}
-
/*
- * Read-only all file systems.
+ * Unmount all file systems.
* We traverse the list in reverse order under the assumption that doing so
* will avoid needing to worry about dependencies.
*/
void
-vfs_rofs(struct proc *p)
+vfs_unmountall(void)
{
struct mount *mp, *nmp;
+ int allerror, error, again = 1;
+ retry:
+ allerror = 0;
TAILQ_FOREACH_REVERSE_SAFE(mp, &mountlist, mntlist, mnt_list, nmp) {
- (void) vfs_readonly(mp, p);
+ if (vfs_busy(mp, VB_WRITE|VB_NOWAIT))
+ continue;
+ /* XXX Here is a race, the next pointer is not locked. */
+ if ((error = dounmount(mp, MNT_FORCE, curproc)) != 0) {
+ printf("unmount of %s failed with error %d\n",
+ mp->mnt_stat.f_mntonname, error);
+ allerror = 1;
+ }
+ }
+
+ if (allerror) {
+ printf("WARNING: some file systems would not unmount\n");
+ if (again) {
+ printf("retrying\n");
+ again = 0;
+ goto retry;
+ }
}
}
@@ -1687,9 +1674,9 @@ vfs_shutdown(struct proc *p)
printf("syncing disks... ");
if (panicstr == 0) {
- /* Take all filesystems to read-only */
+ /* Sync before unmount, in case we hang on something. */
sys_sync(p, NULL, NULL);
- vfs_rofs(p);
+ vfs_unmountall();
}
#if NSOFTRAID > 0