diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2018-02-10 05:24:24 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2018-02-10 05:24:24 +0000 |
commit | 46a5fdccdbec824aec3e3e383277baed4c200dee (patch) | |
tree | d5edda8fa947c8eeb74eb1c49f6b40b68b93b101 /sys | |
parent | d02979485b47a573dd086a214bbd30bce63e5708 (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')
-rw-r--r-- | sys/dev/acpi/acpi.c | 8 | ||||
-rw-r--r-- | sys/isofs/cd9660/cd9660_extern.h | 4 | ||||
-rw-r--r-- | sys/isofs/cd9660/cd9660_vfsops.c | 5 | ||||
-rw-r--r-- | sys/isofs/udf/udf_extern.h | 4 | ||||
-rw-r--r-- | sys/isofs/udf/udf_vfsops.c | 4 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 57 | ||||
-rw-r--r-- | sys/kern/vfs_sync.c | 4 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 6 | ||||
-rw-r--r-- | sys/kern/vfs_vops.c | 135 | ||||
-rw-r--r-- | sys/miscfs/fuse/fuse_vfsops.c | 6 | ||||
-rw-r--r-- | sys/msdosfs/msdosfs_vfsops.c | 9 | ||||
-rw-r--r-- | sys/msdosfs/msdosfsmount.h | 4 | ||||
-rw-r--r-- | sys/nfs/nfs_vfsops.c | 6 | ||||
-rw-r--r-- | sys/ntfs/ntfs_vfsops.c | 6 | ||||
-rw-r--r-- | sys/sys/file.h | 10 | ||||
-rw-r--r-- | sys/sys/mount.h | 8 | ||||
-rw-r--r-- | sys/sys/vnode.h | 3 | ||||
-rw-r--r-- | sys/ufs/ext2fs/ext2fs_extern.h | 4 | ||||
-rw-r--r-- | sys/ufs/ext2fs/ext2fs_vfsops.c | 58 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_extern.h | 4 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_softdep.c | 4 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 56 |
22 files changed, 310 insertions, 95 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index ea23d66040a..4e5fc3f7aa8 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi.c,v 1.338 2018/02/08 09:42:48 deraadt Exp $ */ +/* $OpenBSD: acpi.c,v 1.339 2018/02/10 05:24:23 deraadt Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> @@ -30,6 +30,8 @@ #include <sys/sched.h> #include <sys/reboot.h> #include <sys/sysctl.h> +#include <sys/mount.h> +#include <sys/syscallargs.h> #ifdef HIBERNATE #include <sys/hibernate.h> @@ -2503,6 +2505,7 @@ acpi_sleep_state(struct acpi_softc *sc, int sleepmode) if (config_suspend_all(DVACT_QUIESCE)) goto fail_quiesce; + vfs_stall(curproc, 1); #if NSOFTRAID > 0 sr_quiesce(); #endif @@ -2590,6 +2593,7 @@ fail_suspend: acpi_resume_mp(); #endif + vfs_stall(curproc, 0); bufq_restart(); fail_quiesce: @@ -2612,6 +2616,8 @@ fail_alloc: rw_enter_write(&sc->sc_lck); #endif /* NWSDISPLAY > 0 */ + sys_sync(curproc, NULL, NULL); + /* Restore hw.setperf */ if (cpu_setperf != NULL) cpu_setperf(perflevel); diff --git a/sys/isofs/cd9660/cd9660_extern.h b/sys/isofs/cd9660/cd9660_extern.h index 48b842adce1..8c4bebfa8dd 100644 --- a/sys/isofs/cd9660/cd9660_extern.h +++ b/sys/isofs/cd9660/cd9660_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cd9660_extern.h,v 1.13 2013/06/02 01:07:39 deraadt Exp $ */ +/* $OpenBSD: cd9660_extern.h,v 1.14 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: cd9660_extern.h,v 1.1 1997/01/24 00:24:53 cgd Exp $ */ /*- @@ -87,7 +87,7 @@ int cd9660_unmount(struct mount *, int, struct proc *); int cd9660_root(struct mount *, struct vnode **); int cd9660_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); int cd9660_statfs(struct mount *, struct statfs *, struct proc *); -int cd9660_sync(struct mount *, int, struct ucred *, struct proc *); +int cd9660_sync(struct mount *, int, int, struct ucred *, struct proc *); int cd9660_vget(struct mount *, ino_t, struct vnode **); int cd9660_fhtovp(struct mount *, struct fid *, struct vnode **); int cd9660_vptofh(struct vnode *, struct fid *); diff --git a/sys/isofs/cd9660/cd9660_vfsops.c b/sys/isofs/cd9660/cd9660_vfsops.c index efe2e4abdb5..ac3df59ad1b 100644 --- a/sys/isofs/cd9660/cd9660_vfsops.c +++ b/sys/isofs/cd9660/cd9660_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cd9660_vfsops.c,v 1.86 2017/12/30 23:08:29 guenther Exp $ */ +/* $OpenBSD: cd9660_vfsops.c,v 1.87 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: cd9660_vfsops.c,v 1.26 1997/06/13 15:38:58 pk Exp $ */ /*- @@ -644,9 +644,10 @@ cd9660_statfs(mp, sbp, p) /* ARGSUSED */ int -cd9660_sync(mp, waitfor, cred, p) +cd9660_sync(mp, waitfor, stall, cred, p) struct mount *mp; int waitfor; + int stall; struct ucred *cred; struct proc *p; { diff --git a/sys/isofs/udf/udf_extern.h b/sys/isofs/udf/udf_extern.h index 07859f3fc4b..c48782c820c 100644 --- a/sys/isofs/udf/udf_extern.h +++ b/sys/isofs/udf/udf_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: udf_extern.h,v 1.13 2013/06/02 15:35:18 deraadt Exp $ */ +/* $OpenBSD: udf_extern.h,v 1.14 2018/02/10 05:24:23 deraadt Exp $ */ /* * Written by Pedro Martelletto <pedro@ambientworks.net> in February 2005. @@ -26,7 +26,7 @@ int udf_root(struct mount *, struct vnode **); int udf_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); int udf_statfs(struct mount *, struct statfs *, struct proc *); int udf_vget(struct mount *, ino_t, struct vnode **); -int udf_sync(struct mount *, int, struct ucred *, struct proc *); +int udf_sync(struct mount *, int, int, struct ucred *, struct proc *); int udf_sysctl(int *, u_int, void *, size_t *, void *, size_t, struct proc *); int udf_checkexp(struct mount *, struct mbuf *, int *, struct ucred **); int udf_fhtovp(struct mount *, struct fid *, struct vnode **); diff --git a/sys/isofs/udf/udf_vfsops.c b/sys/isofs/udf/udf_vfsops.c index 56ef21fa34f..8a0173db611 100644 --- a/sys/isofs/udf/udf_vfsops.c +++ b/sys/isofs/udf/udf_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udf_vfsops.c,v 1.61 2017/12/11 05:27:40 deraadt Exp $ */ +/* $OpenBSD: udf_vfsops.c,v 1.62 2018/02/10 05:24:23 deraadt Exp $ */ /* * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org> @@ -537,7 +537,7 @@ udf_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) } int -udf_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p) +udf_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p) { return (0); } 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 } /* diff --git a/sys/kern/vfs_sync.c b/sys/kern/vfs_sync.c index 86fda887951..bb8ee505e81 100644 --- a/sys/kern/vfs_sync.c +++ b/sys/kern/vfs_sync.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_sync.c,v 1.56 2017/02/14 10:31:15 mpi Exp $ */ +/* $OpenBSD: vfs_sync.c,v 1.57 2018/02/10 05:24:23 deraadt Exp $ */ /* * Portions of this code are: @@ -339,7 +339,7 @@ sync_fsync(void *v) if (vfs_busy(mp, VB_READ|VB_NOWAIT) == 0) { asyncflag = mp->mnt_flag & MNT_ASYNC; mp->mnt_flag &= ~MNT_ASYNC; - VFS_SYNC(mp, MNT_LAZY, ap->a_cred, ap->a_p); + VFS_SYNC(mp, MNT_LAZY, 0, ap->a_cred, ap->a_p); if (asyncflag) mp->mnt_flag |= MNT_ASYNC; vfs_unbusy(mp); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 675a4d64d50..1edad2495cd 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.274 2018/01/02 06:38:45 guenther Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.275 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -494,7 +494,7 @@ dounmount_leaf(struct mount *mp, int flags, struct proc *p) mp->mnt_syncer = NULL; } if (((mp->mnt_flag & MNT_RDONLY) || - (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) || + (error = VFS_SYNC(mp, MNT_WAIT, 0, p->p_ucred, p)) == 0) || (flags & MNT_FORCE)) error = VFS_UNMOUNT(mp, flags, p); @@ -543,7 +543,7 @@ sys_sync(struct proc *p, void *v, register_t *retval) asyncflag = mp->mnt_flag & MNT_ASYNC; mp->mnt_flag &= ~MNT_ASYNC; uvm_vnp_sync(mp); - VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p); + VFS_SYNC(mp, MNT_NOWAIT, 0, p->p_ucred, p); if (asyncflag) mp->mnt_flag |= MNT_ASYNC; } diff --git a/sys/kern/vfs_vops.c b/sys/kern/vfs_vops.c index f579134aeed..42ba4eecf00 100644 --- a/sys/kern/vfs_vops.c +++ b/sys/kern/vfs_vops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_vops.c,v 1.16 2016/05/23 09:31:28 natano Exp $ */ +/* $OpenBSD: vfs_vops.c,v 1.17 2018/02/10 05:24:23 deraadt Exp $ */ /* * Copyright (c) 2010 Thordur I. Bjornsson <thib@openbsd.org> * @@ -76,6 +76,7 @@ int VOP_LOOKUP(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp) { + int r; struct vop_lookup_args a; a.a_dvp = dvp; a.a_vpp = vpp; @@ -84,13 +85,17 @@ VOP_LOOKUP(struct vnode *dvp, struct vnode **vpp, if (dvp->v_op->vop_lookup == NULL) return (EOPNOTSUPP); - return ((dvp->v_op->vop_lookup)(&a)); + dvp->v_inflight++; + r = (dvp->v_op->vop_lookup)(&a); + dvp->v_inflight--; + return r; } int VOP_CREATE(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap) { + int r; struct vop_create_args a; a.a_dvp = dvp; a.a_vpp = vpp; @@ -102,13 +107,17 @@ VOP_CREATE(struct vnode *dvp, struct vnode **vpp, if (dvp->v_op->vop_create == NULL) return (EOPNOTSUPP); - return ((dvp->v_op->vop_create)(&a)); + dvp->v_inflight++; + r = (dvp->v_op->vop_create)(&a); + dvp->v_inflight--; + return r; } int VOP_MKNOD(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap) { + int r; struct vop_mknod_args a; a.a_dvp = dvp; a.a_vpp = vpp; @@ -120,12 +129,16 @@ VOP_MKNOD(struct vnode *dvp, struct vnode **vpp, if (dvp->v_op->vop_mknod == NULL) return (EOPNOTSUPP); - return ((dvp->v_op->vop_mknod)(&a)); + dvp->v_inflight++; + r = (dvp->v_op->vop_mknod)(&a); + dvp->v_inflight--; + return r; } int VOP_OPEN(struct vnode *vp, int mode, struct ucred *cred, struct proc *p) { + int r; struct vop_open_args a; a.a_vp = vp; a.a_mode = mode; @@ -135,12 +148,16 @@ VOP_OPEN(struct vnode *vp, int mode, struct ucred *cred, struct proc *p) if (vp->v_op->vop_open == NULL) return (EOPNOTSUPP); - return ((vp->v_op->vop_open)(&a)); + vp->v_inflight++; + r = (vp->v_op->vop_open)(&a); + vp->v_inflight--; + return r; } int VOP_CLOSE(struct vnode *vp, int fflag, struct ucred *cred, struct proc *p) { + int r; struct vop_close_args a; a.a_vp = vp; a.a_fflag = fflag; @@ -152,7 +169,10 @@ VOP_CLOSE(struct vnode *vp, int fflag, struct ucred *cred, struct proc *p) if (vp->v_op->vop_close == NULL) return (EOPNOTSUPP); - return ((vp->v_op->vop_close)(&a)); + vp->v_inflight++; + r = (vp->v_op->vop_close)(&a); + vp->v_inflight--; + return r; } int @@ -192,6 +212,7 @@ int VOP_SETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred, struct proc *p) { + int r; struct vop_setattr_args a; a.a_vp = vp; a.a_vap = vap; @@ -203,7 +224,10 @@ VOP_SETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred, if (vp->v_op->vop_setattr == NULL) return (EOPNOTSUPP); - return ((vp->v_op->vop_setattr)(&a)); + vp->v_inflight++; + r = (vp->v_op->vop_setattr)(&a); + vp->v_inflight--; + return r; } int @@ -227,6 +251,7 @@ int VOP_WRITE(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) { + int r; struct vop_write_args a; a.a_vp = vp; a.a_uio = uio; @@ -238,13 +263,17 @@ VOP_WRITE(struct vnode *vp, struct uio *uio, int ioflag, if (vp->v_op->vop_write == NULL) return (EOPNOTSUPP); - return ((vp->v_op->vop_write)(&a)); + vp->v_inflight++; + r = (vp->v_op->vop_write)(&a); + vp->v_inflight--; + return r; } int VOP_IOCTL(struct vnode *vp, u_long command, void *data, int fflag, struct ucred *cred, struct proc *p) { + int r; struct vop_ioctl_args a; a.a_vp = vp; a.a_command = command; @@ -256,8 +285,10 @@ VOP_IOCTL(struct vnode *vp, u_long command, void *data, int fflag, if (vp->v_op->vop_ioctl == NULL) return (EOPNOTSUPP); - return ((vp->v_op->vop_ioctl)(&a)); - + vp->v_inflight++; + r = (vp->v_op->vop_ioctl)(&a); + vp->v_inflight--; + return r; } int @@ -305,6 +336,7 @@ int VOP_FSYNC(struct vnode *vp, struct ucred *cred, int waitfor, struct proc *p) { + int r; struct vop_fsync_args a; a.a_vp = vp; a.a_cred = cred; @@ -316,12 +348,16 @@ VOP_FSYNC(struct vnode *vp, struct ucred *cred, int waitfor, if (vp->v_op->vop_fsync == NULL) return (EOPNOTSUPP); - return ((vp->v_op->vop_fsync)(&a)); + vp->v_inflight++; + r = (vp->v_op->vop_fsync)(&a); + vp->v_inflight--; + return r; } int VOP_REMOVE(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { + int r; struct vop_remove_args a; a.a_dvp = dvp; a.a_vp = vp; @@ -333,12 +369,16 @@ VOP_REMOVE(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) if (dvp->v_op->vop_remove == NULL) return (EOPNOTSUPP); - return ((dvp->v_op->vop_remove)(&a)); + dvp->v_inflight++; + r = (dvp->v_op->vop_remove)(&a); + dvp->v_inflight--; + return r; } int VOP_LINK(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { + int r; struct vop_link_args a; a.a_dvp = dvp; a.a_vp = vp; @@ -349,7 +389,12 @@ VOP_LINK(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) if (dvp->v_op->vop_link == NULL) return (EOPNOTSUPP); - return ((dvp->v_op->vop_link)(&a)); + dvp->v_inflight++; + vp->v_inflight++; + r = (dvp->v_op->vop_link)(&a); + dvp->v_inflight--; + vp->v_inflight--; + return r; } int @@ -357,6 +402,7 @@ VOP_RENAME(struct vnode *fdvp, struct vnode *fvp, struct componentname *fcnp, struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp) { + int r; struct vop_rename_args a; a.a_fdvp = fdvp; a.a_fvp = fvp; @@ -370,13 +416,19 @@ VOP_RENAME(struct vnode *fdvp, struct vnode *fvp, if (fdvp->v_op->vop_rename == NULL) return (EOPNOTSUPP); - return ((fdvp->v_op->vop_rename)(&a)); + fdvp->v_inflight++; + tdvp->v_inflight++; + r = (fdvp->v_op->vop_rename)(&a); + fdvp->v_inflight--; + tdvp->v_inflight--; + return r; } int VOP_MKDIR(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap) { + int r; struct vop_mkdir_args a; a.a_dvp = dvp; a.a_vpp = vpp; @@ -388,12 +440,16 @@ VOP_MKDIR(struct vnode *dvp, struct vnode **vpp, if (dvp->v_op->vop_mkdir == NULL) return (EOPNOTSUPP); - return ((dvp->v_op->vop_mkdir)(&a)); + dvp->v_inflight++; + r = (dvp->v_op->vop_mkdir)(&a); + dvp->v_inflight--; + return r; } int VOP_RMDIR(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { + int r; struct vop_rmdir_args a; a.a_dvp = dvp; a.a_vp = vp; @@ -405,13 +461,19 @@ VOP_RMDIR(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) if (dvp->v_op->vop_rmdir == NULL) return (EOPNOTSUPP); - return ((dvp->v_op->vop_rmdir)(&a)); + dvp->v_inflight++; + vp->v_inflight++; + r = (dvp->v_op->vop_rmdir)(&a); + dvp->v_inflight--; + vp->v_inflight--; + return r; } int VOP_SYMLINK(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap, char *target) { + int r; struct vop_symlink_args a; a.a_dvp = dvp; a.a_vpp = vpp; @@ -424,13 +486,17 @@ VOP_SYMLINK(struct vnode *dvp, struct vnode **vpp, if (dvp->v_op->vop_symlink == NULL) return (EOPNOTSUPP); - return ((dvp->v_op->vop_symlink)(&a)); + dvp->v_inflight++; + r = (dvp->v_op->vop_symlink)(&a); + dvp->v_inflight--; + return r; } int VOP_READDIR(struct vnode *vp, struct uio *uio, struct ucred *cred, int *eofflag) { + int r; struct vop_readdir_args a; a.a_vp = vp; a.a_uio = uio; @@ -442,12 +508,16 @@ VOP_READDIR(struct vnode *vp, struct uio *uio, struct ucred *cred, if (vp->v_op->vop_readdir == NULL) return (EOPNOTSUPP); - return ((vp->v_op->vop_readdir)(&a)); + vp->v_inflight++; + r = (vp->v_op->vop_readdir)(&a); + vp->v_inflight--; + return r; } int VOP_READLINK(struct vnode *vp, struct uio *uio, struct ucred *cred) { + int r; struct vop_readlink_args a; a.a_vp = vp; a.a_uio = uio; @@ -458,12 +528,16 @@ VOP_READLINK(struct vnode *vp, struct uio *uio, struct ucred *cred) if (vp->v_op->vop_readlink == NULL) return (EOPNOTSUPP); - return ((vp->v_op->vop_readlink)(&a)); + vp->v_inflight++; + r = (vp->v_op->vop_readlink)(&a); + vp->v_inflight--; + return r; } int VOP_ABORTOP(struct vnode *dvp, struct componentname *cnp) { + int r; struct vop_abortop_args a; a.a_dvp = dvp; a.a_cnp = cnp; @@ -471,7 +545,10 @@ VOP_ABORTOP(struct vnode *dvp, struct componentname *cnp) if (dvp->v_op->vop_abortop == NULL) return (EOPNOTSUPP); - return ((dvp->v_op->vop_abortop)(&a)); + dvp->v_inflight++; + r = (dvp->v_op->vop_abortop)(&a); + dvp->v_inflight--; + return r; } int @@ -492,6 +569,7 @@ VOP_INACTIVE(struct vnode *vp, struct proc *p) int VOP_RECLAIM(struct vnode *vp, struct proc *p) { + int r; struct vop_reclaim_args a; a.a_vp = vp; a.a_p = p; @@ -499,7 +577,10 @@ VOP_RECLAIM(struct vnode *vp, struct proc *p) if (vp->v_op->vop_reclaim == NULL) return (EOPNOTSUPP); - return ((vp->v_op->vop_reclaim)(&a)); + vp->v_inflight++; + r = (vp->v_op->vop_reclaim)(&a); + vp->v_inflight--; + return r; } int @@ -519,6 +600,7 @@ VOP_LOCK(struct vnode *vp, int flags, struct proc *p) int VOP_UNLOCK(struct vnode *vp, struct proc *p) { + int r; struct vop_unlock_args a; a.a_vp = vp; a.a_p = p; @@ -526,7 +608,10 @@ VOP_UNLOCK(struct vnode *vp, struct proc *p) if (vp->v_op->vop_unlock == NULL) return (EOPNOTSUPP); - return ((vp->v_op->vop_unlock)(&a)); + vp->v_inflight++; + r = (vp->v_op->vop_unlock)(&a); + vp->v_inflight--; + return r; } int @@ -598,6 +683,7 @@ VOP_PATHCONF(struct vnode *vp, int name, register_t *retval) int VOP_ADVLOCK(struct vnode *vp, void *id, int op, struct flock *fl, int flags) { + int r; struct vop_advlock_args a; a.a_vp = vp; a.a_id = id; @@ -608,7 +694,10 @@ VOP_ADVLOCK(struct vnode *vp, void *id, int op, struct flock *fl, int flags) if (vp->v_op->vop_advlock == NULL) return (EOPNOTSUPP); - return ((vp->v_op->vop_advlock)(&a)); + vp->v_inflight++; + r = (vp->v_op->vop_advlock)(&a); + vp->v_inflight--; + return r; } int diff --git a/sys/miscfs/fuse/fuse_vfsops.c b/sys/miscfs/fuse/fuse_vfsops.c index 7867ff60579..7f7b044f458 100644 --- a/sys/miscfs/fuse/fuse_vfsops.c +++ b/sys/miscfs/fuse/fuse_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fuse_vfsops.c,v 1.31 2018/01/04 10:51:11 mpi Exp $ */ +/* $OpenBSD: fuse_vfsops.c,v 1.32 2018/02/10 05:24:23 deraadt Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com> * @@ -40,7 +40,7 @@ int fusefs_unmount(struct mount *, int, struct proc *); int fusefs_root(struct mount *, struct vnode **); int fusefs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); int fusefs_statfs(struct mount *, struct statfs *, struct proc *); -int fusefs_sync(struct mount *, int, struct ucred *, struct proc *); +int fusefs_sync(struct mount *, int, int, struct ucred *, struct proc *); int fusefs_vget(struct mount *, ino_t, struct vnode **); int fusefs_fhtovp(struct mount *, struct fid *, struct vnode **); int fusefs_vptofh(struct vnode *, struct fid *); @@ -239,7 +239,7 @@ fusefs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) } int -fusefs_sync(struct mount *mp, int waitfor, struct ucred *cred, +fusefs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p) { return (0); diff --git a/sys/msdosfs/msdosfs_vfsops.c b/sys/msdosfs/msdosfs_vfsops.c index 67af60dcbf9..f2a7a5de845 100644 --- a/sys/msdosfs/msdosfs_vfsops.c +++ b/sys/msdosfs/msdosfs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: msdosfs_vfsops.c,v 1.86 2017/12/30 23:08:29 guenther Exp $ */ +/* $OpenBSD: msdosfs_vfsops.c,v 1.87 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: msdosfs_vfsops.c,v 1.48 1997/10/18 02:54:57 briggs Exp $ */ /*- @@ -80,7 +80,7 @@ int msdosfs_start(struct mount *, int, struct proc *); int msdosfs_unmount(struct mount *, int, struct proc *); int msdosfs_root(struct mount *, struct vnode **); int msdosfs_statfs(struct mount *, struct statfs *, struct proc *); -int msdosfs_sync(struct mount *, int, struct ucred *, struct proc *); +int msdosfs_sync(struct mount *, int, int, struct ucred *, struct proc *); int msdosfs_fhtovp(struct mount *, struct fid *, struct vnode **); int msdosfs_vptofh(struct vnode *, struct fid *); int msdosfs_check_export(struct mount *mp, struct mbuf *nam, @@ -118,7 +118,7 @@ msdosfs_mount(struct mount *mp, const char *path, void *data, if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) && (mp->mnt_flag & MNT_RDONLY)) { mp->mnt_flag &= ~MNT_RDONLY; - VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p); + VFS_SYNC(mp, MNT_WAIT, 0, p->p_ucred, p); mp->mnt_flag |= MNT_RDONLY; flags = WRITECLOSE; @@ -689,7 +689,8 @@ msdosfs_sync_vnode(struct vnode *vp, void *arg) int -msdosfs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p) +msdosfs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, + struct proc *p) { struct msdosfsmount *pmp = VFSTOMSDOSFS(mp); struct msdosfs_sync_arg msa; diff --git a/sys/msdosfs/msdosfsmount.h b/sys/msdosfs/msdosfsmount.h index dc892feab1f..23b5a65d208 100644 --- a/sys/msdosfs/msdosfsmount.h +++ b/sys/msdosfs/msdosfsmount.h @@ -1,4 +1,4 @@ -/* $OpenBSD: msdosfsmount.h,v 1.21 2016/05/21 18:11:36 natano Exp $ */ +/* $OpenBSD: msdosfsmount.h,v 1.22 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: msdosfsmount.h,v 1.16 1997/10/17 11:24:24 ws Exp $ */ /*- @@ -206,7 +206,7 @@ int msdosfs_unmount(struct mount *, int, struct proc *); int msdosfs_root(struct mount *, struct vnode **); int msdosfs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); int msdosfs_statfs(struct mount *, struct statfs *, struct proc *); -int msdosfs_sync(struct mount *, int, struct ucred *, struct proc *); +int msdosfs_sync(struct mount *, int, int, struct ucred *, struct proc *); int msdosfs_fhtovp(struct mount *, struct fid *, struct vnode **); int msdosfs_vptofh(struct vnode *, struct fid *); int msdosfs_init(struct vfsconf *); diff --git a/sys/nfs/nfs_vfsops.c b/sys/nfs/nfs_vfsops.c index 65874a1e2b1..259b2f7f0d6 100644 --- a/sys/nfs/nfs_vfsops.c +++ b/sys/nfs/nfs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_vfsops.c,v 1.115 2017/12/11 05:27:40 deraadt Exp $ */ +/* $OpenBSD: nfs_vfsops.c,v 1.116 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: nfs_vfsops.c,v 1.46.4.1 1996/05/25 22:40:35 fvdl Exp $ */ /* @@ -80,7 +80,7 @@ int nfs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); int nfs_root(struct mount *, struct vnode **); int nfs_start(struct mount *, int, struct proc *); int nfs_statfs(struct mount *, struct statfs *, struct proc *); -int nfs_sync(struct mount *, int, struct ucred *, struct proc *); +int nfs_sync(struct mount *, int, int, struct ucred *, struct proc *); int nfs_unmount(struct mount *, int, struct proc *); int nfs_vget(struct mount *, ino_t, struct vnode **); int nfs_vptofh(struct vnode *, struct fid *); @@ -729,7 +729,7 @@ nfs_root(struct mount *mp, struct vnode **vpp) * Flush out the buffer cache */ int -nfs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p) +nfs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p) { struct vnode *vp; int error, allerror = 0; diff --git a/sys/ntfs/ntfs_vfsops.c b/sys/ntfs/ntfs_vfsops.c index 6ceac5b3288..9ad5ac1e01d 100644 --- a/sys/ntfs/ntfs_vfsops.c +++ b/sys/ntfs/ntfs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntfs_vfsops.c,v 1.57 2017/12/11 05:27:40 deraadt Exp $ */ +/* $OpenBSD: ntfs_vfsops.c,v 1.58 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: ntfs_vfsops.c,v 1.7 2003/04/24 07:50:19 christos Exp $ */ /*- @@ -60,7 +60,7 @@ int ntfs_root(struct mount *, struct vnode **); int ntfs_start(struct mount *, int, struct proc *); int ntfs_statfs(struct mount *, struct statfs *, struct proc *); -int ntfs_sync(struct mount *, int, struct ucred *, +int ntfs_sync(struct mount *, int, int, struct ucred *, struct proc *); int ntfs_unmount(struct mount *, int, struct proc *); int ntfs_vget(struct mount *mp, ino_t ino, @@ -612,7 +612,7 @@ ntfs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) } int -ntfs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p) +ntfs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p) { /*DPRINTF("ntfs_sync():\n");*/ return (0); diff --git a/sys/sys/file.h b/sys/sys/file.h index 23c2b868531..ef27cd5cc15 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -1,4 +1,4 @@ -/* $OpenBSD: file.h,v 1.39 2018/01/02 06:40:55 guenther Exp $ */ +/* $OpenBSD: file.h,v 1.40 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: file.h,v 1.11 1995/03/26 20:24:13 jtc Exp $ */ /* @@ -89,7 +89,13 @@ struct file { #define FILE_IS_USABLE(fp) \ (((fp)->f_iflags & FIF_LARVAL) == 0) -#define FREF(fp) do { (fp)->f_count++; } while (0) +#define FREF(fp) \ + do { \ + extern struct rwlock vfs_stall_lock; \ + rw_enter_read(&vfs_stall_lock); \ + rw_exit_read(&vfs_stall_lock); \ + (fp)->f_count++; \ + } while (0) #define FRELE(fp,p) (--(fp)->f_count == 0 ? fdrop(fp, p) : 0) #define FILE_SET_MATURE(fp,p) do { \ diff --git a/sys/sys/mount.h b/sys/sys/mount.h index fbed4bc6fe9..9ec04f6e729 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mount.h,v 1.134 2018/01/05 05:54:36 deraadt Exp $ */ +/* $OpenBSD: mount.h,v 1.135 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: mount.h,v 1.48 1996/02/18 11:55:47 fvdl Exp $ */ /* @@ -389,6 +389,7 @@ struct mount { #define MNT_DELEXPORT 0x00020000 /* delete export host lists */ #define MNT_RELOAD 0x00040000 /* reload filesystem data */ #define MNT_FORCE 0x00080000 /* force unmount or readonly change */ +#define MNT_STALLED 0x00100000 /* filesystem stalled */ #define MNT_WANTRDWR 0x02000000 /* want upgrade to read/write */ #define MNT_SOFTDEP 0x04000000 /* soft dependencies being done */ #define MNT_DOOMED 0x08000000 /* device behind filesystem is gone */ @@ -505,7 +506,7 @@ struct vfsops { caddr_t arg, struct proc *p); int (*vfs_statfs)(struct mount *mp, struct statfs *sbp, struct proc *p); - int (*vfs_sync)(struct mount *mp, int waitfor, + int (*vfs_sync)(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p); int (*vfs_vget)(struct mount *mp, ino_t ino, struct vnode **vpp); @@ -526,7 +527,7 @@ struct vfsops { #define VFS_ROOT(MP, VPP) (*(MP)->mnt_op->vfs_root)(MP, VPP) #define VFS_QUOTACTL(MP,C,U,A,P) (*(MP)->mnt_op->vfs_quotactl)(MP, C, U, A, P) #define VFS_STATFS(MP, SBP, P) (*(MP)->mnt_op->vfs_statfs)(MP, SBP, P) -#define VFS_SYNC(MP, WAIT, C, P) (*(MP)->mnt_op->vfs_sync)(MP, WAIT, C, P) +#define VFS_SYNC(MP, W, S, C, P) (*(MP)->mnt_op->vfs_sync)(MP, W, S, C, P) #define VFS_VGET(MP, INO, VPP) (*(MP)->mnt_op->vfs_vget)(MP, INO, VPP) #define VFS_FHTOVP(MP, FIDP, VPP) \ (*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, VPP) @@ -573,6 +574,7 @@ int vfs_mountedon(struct vnode *); int vfs_rootmountalloc(char *, char *, struct mount **); void vfs_unbusy(struct mount *); extern TAILQ_HEAD(mntlist, mount) mountlist; +int vfs_stall(struct proc *, int); struct mount *getvfs(fsid_t *); /* return vfs given fsid */ /* process mount export info */ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 32a2d96f71c..f113739395e 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vnode.h,v 1.142 2017/12/14 20:20:38 deraadt Exp $ */ +/* $OpenBSD: vnode.h,v 1.143 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: vnode.h,v 1.38 1996/02/29 20:59:05 cgd Exp $ */ /* @@ -99,6 +99,7 @@ struct vnode { u_int v_bioflag; u_int v_holdcnt; /* buffer references */ u_int v_id; /* capability identifier */ + u_int v_inflight; struct mount *v_mount; /* ptr to vfs we are in */ TAILQ_ENTRY(vnode) v_freelist; /* vnode freelist */ LIST_ENTRY(vnode) v_mntvnodes; /* vnodes for mount point */ diff --git a/sys/ufs/ext2fs/ext2fs_extern.h b/sys/ufs/ext2fs/ext2fs_extern.h index a0253a1470e..68c71ca1e9e 100644 --- a/sys/ufs/ext2fs/ext2fs_extern.h +++ b/sys/ufs/ext2fs/ext2fs_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ext2fs_extern.h,v 1.36 2016/08/10 07:53:02 natano Exp $ */ +/* $OpenBSD: ext2fs_extern.h,v 1.37 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: ext2fs_extern.h,v 1.1 1997/06/11 09:33:55 bouyer Exp $ */ /*- @@ -105,7 +105,7 @@ int ext2fs_mountfs(struct vnode *, struct mount *, struct proc *); int ext2fs_unmount(struct mount *, int, struct proc *); int ext2fs_flushfiles(struct mount *, int, struct proc *); int ext2fs_statfs(struct mount *, struct statfs *, struct proc *); -int ext2fs_sync(struct mount *, int, struct ucred *, struct proc *); +int ext2fs_sync(struct mount *, int, int, struct ucred *, struct proc *); int ext2fs_vget(struct mount *, ino_t, struct vnode **); int ext2fs_fhtovp(struct mount *, struct fid *, struct vnode **); int ext2fs_vptofh(struct vnode *, struct fid *); diff --git a/sys/ufs/ext2fs/ext2fs_vfsops.c b/sys/ufs/ext2fs/ext2fs_vfsops.c index 114285d423c..55cfacddb2e 100644 --- a/sys/ufs/ext2fs/ext2fs_vfsops.c +++ b/sys/ufs/ext2fs/ext2fs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ext2fs_vfsops.c,v 1.101 2017/12/30 23:08:29 guenther Exp $ */ +/* $OpenBSD: ext2fs_vfsops.c,v 1.102 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: ext2fs_vfsops.c,v 1.1 1997/06/11 09:34:07 bouyer Exp $ */ /* @@ -696,6 +696,8 @@ int ext2fs_sync_vnode(struct vnode *vp, void *); struct ext2fs_sync_args { int allerror; int waitfor; + int nlink0; + int inflight; struct proc *p; struct ucred *cred; }; @@ -705,22 +707,34 @@ ext2fs_sync_vnode(struct vnode *vp, void *args) { struct ext2fs_sync_args *esa = args; struct inode *ip; - int error; + int error, nlink0 = 0; - ip = VTOI(vp); - if (vp->v_type == VNON || - ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && - LIST_EMPTY(&vp->v_dirtyblkhd)) || - esa->waitfor == MNT_LAZY) { + if (vp->v_type == VNON) return (0); + + if (vp->v_inflight) + esa->inflight = MIN(esa->inflight+1, 65536); + + ip = VTOI(vp); + + if (ip->i_e2fs_nlink == 0) + nlink0 = 1; + + if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && + LIST_EMPTY(&vp->v_dirtyblkhd)) { + goto end; } - if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT, esa->p)) - return (0); + if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT, esa->p)) { + nlink0 = 1; /* potentially */ + goto end; + } if ((error = VOP_FSYNC(vp, esa->cred, esa->waitfor, esa->p)) != 0) esa->allerror = error; vput(vp); +end: + esa->nlink0 = MIN(esa->nlink0 + nlink0, 65536); return (0); } /* @@ -731,11 +745,12 @@ ext2fs_sync_vnode(struct vnode *vp, void *args) * Should always be called with the mount point locked. */ int -ext2fs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p) +ext2fs_sync(struct mount *mp, int waitfor, int stall, + struct ucred *cred, struct proc *p) { struct ufsmount *ump = VFSTOUFS(mp); struct m_ext2fs *fs; - int error, allerror = 0; + int error, allerror = 0, state, fmod; struct ext2fs_sync_args esa; fs = ump->um_e2fs; @@ -751,6 +766,8 @@ ext2fs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p) esa.cred = cred; esa.allerror = 0; esa.waitfor = waitfor; + esa.nlink0 = 0; + esa.inflight = 0; vfs_mount_foreach_vnode(mp, ext2fs_sync_vnode, &esa); if (esa.allerror != 0) @@ -768,12 +785,31 @@ ext2fs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p) /* * Write back modified superblock. */ + state = fs->e2fs.e2fs_state; + fmod = fs->e2fs_fmod; + if (stall && fs->e2fs_ronly == 0) { + fs->e2fs_fmod = 1; + if (allerror == 0 && esa.nlink0 == 0 && esa.inflight == 0) { + if ((fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) + fs->e2fs.e2fs_state = E2FS_ISCLEAN; +#if 0 + printf("%s force clean (dangling %d inflight %d)\n", + mp->mnt_stat.f_mntonname, esa.nlink0, esa.inflight); +#endif + } else { + fs->e2fs.e2fs_state = 0; + printf("%s force dirty (dangling %d inflight %d)\n", + mp->mnt_stat.f_mntonname, esa.nlink0, esa.inflight); + } + } if (fs->e2fs_fmod != 0) { fs->e2fs_fmod = 0; fs->e2fs.e2fs_wtime = time_second; if ((error = ext2fs_cgupdate(ump, waitfor))) allerror = error; } + fs->e2fs.e2fs_state = state; + fs->e2fs_fmod = fmod; return (allerror); } diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h index 45de5724f2f..0abe9d73b59 100644 --- a/sys/ufs/ffs/ffs_extern.h +++ b/sys/ufs/ffs/ffs_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_extern.h,v 1.43 2016/08/10 08:04:57 natano Exp $ */ +/* $OpenBSD: ffs_extern.h,v 1.44 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: ffs_extern.h,v 1.4 1996/02/09 22:22:22 christos Exp $ */ /* @@ -144,7 +144,7 @@ int ffs_oldfscompat(struct fs *); int ffs_unmount(struct mount *, int, struct proc *); int ffs_flushfiles(struct mount *, int, struct proc *); int ffs_statfs(struct mount *, struct statfs *, struct proc *); -int ffs_sync(struct mount *, int, struct ucred *, struct proc *); +int ffs_sync(struct mount *, int, int, struct ucred *, struct proc *); int ffs_vget(struct mount *, ino_t, struct vnode **); int ffs_fhtovp(struct mount *, struct fid *, struct vnode **); int ffs_vptofh(struct vnode *, struct fid *); diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index f98dcd25286..97b3d244025 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_softdep.c,v 1.137 2017/12/13 16:38:34 beck Exp $ */ +/* $OpenBSD: ffs_softdep.c,v 1.138 2018/02/10 05:24:23 deraadt Exp $ */ /* * Copyright 1998, 2000 Marshall Kirk McKusick. All Rights Reserved. @@ -4945,7 +4945,7 @@ loop: */ if (vn_isdisk(vp, NULL) && vp->v_specmountpoint && !VOP_ISLOCKED(vp) && - (error = VFS_SYNC(vp->v_specmountpoint, MNT_WAIT, ap->a_cred, + (error = VFS_SYNC(vp->v_specmountpoint, MNT_WAIT, 0, ap->a_cred, ap->a_p)) != 0) return (error); return (0); diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 9492e50d6fd..874551b3ea3 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_vfsops.c,v 1.171 2017/12/30 23:08:29 guenther Exp $ */ +/* $OpenBSD: ffs_vfsops.c,v 1.172 2018/02/10 05:24:23 deraadt Exp $ */ /* $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */ /* @@ -243,7 +243,7 @@ ffs_mount(struct mount *mp, const char *path, void *data, if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { /* Flush any dirty data */ - VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p); + VFS_SYNC(mp, MNT_WAIT, 0, p->p_ucred, p); /* * Get rid of files open for writing. @@ -1141,20 +1141,26 @@ struct ffs_sync_args { int allerror; struct proc *p; int waitfor; + int nlink0; + int inflight; struct ucred *cred; }; int -ffs_sync_vnode(struct vnode *vp, void *arg) { +ffs_sync_vnode(struct vnode *vp, void *arg) +{ struct ffs_sync_args *fsa = arg; struct inode *ip; - int error; + int error, nlink0 = 0; if (vp->v_type == VNON) return (0); ip = VTOI(vp); + if (vp->v_inflight && !(vp->v_type == VCHR || vp->v_type == VBLK)) + fsa->inflight = MIN(fsa->inflight+1, 65536); + /* * If unmounting or converting rw to ro, then stop deferring * timestamp writes. @@ -1164,20 +1170,27 @@ ffs_sync_vnode(struct vnode *vp, void *arg) { UFS_UPDATE(ip, 1); } + if (ip->i_effnlink == 0) + nlink0 = 1; + if ((ip->i_flag & - (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && - LIST_EMPTY(&vp->v_dirtyblkhd)) { - return (0); + (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && + LIST_EMPTY(&vp->v_dirtyblkhd)) { + goto end; } - if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT, fsa->p)) - return (0); + if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT, fsa->p)) { + nlink0 = 1; /* potentially.. */ + goto end; + } if ((error = VOP_FSYNC(vp, fsa->cred, fsa->waitfor, fsa->p))) fsa->allerror = error; VOP_UNLOCK(vp, fsa->p); vrele(vp); +end: + fsa->nlink0 = MIN(fsa->nlink0 + nlink0, 65536); return (0); } @@ -1189,11 +1202,11 @@ ffs_sync_vnode(struct vnode *vp, void *arg) { * Should always be called with the mount point locked. */ int -ffs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p) +ffs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p) { struct ufsmount *ump = VFSTOUFS(mp); struct fs *fs; - int error, allerror = 0, count; + int error, allerror = 0, count, clean, fmod; struct ffs_sync_args fsa; fs = ump->um_fs; @@ -1214,6 +1227,8 @@ ffs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p) fsa.p = p; fsa.cred = cred; fsa.waitfor = waitfor; + fsa.nlink0 = 0; + fsa.inflight = 0; /* * Don't traverse the vnode list if we want to skip all of them. @@ -1243,9 +1258,26 @@ ffs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p) /* * Write back modified superblock. */ - + clean = fs->fs_clean; + fmod = fs->fs_fmod; + if (stall && fs->fs_ronly == 0) { + fs->fs_fmod = 1; + if (allerror == 0 && fsa.nlink0 == 0 && fsa.inflight == 0) { + fs->fs_clean = (fs->fs_flags & FS_UNCLEAN) ? 0 : 1; +#if 0 + printf("%s force clean (dangling %d inflight %d)\n", + mp->mnt_stat.f_mntonname, fsa.nlink0, fsa.inflight); +#endif + } else { + fs->fs_clean = 0; + printf("%s force dirty (dangling %d inflight %d)\n", + mp->mnt_stat.f_mntonname, fsa.nlink0, fsa.inflight); + } + } if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0) allerror = error; + fs->fs_clean = clean; + fs->fs_fmod = fmod; return (allerror); } |