From: deraadt Date: Sat, 10 Feb 2018 05:24:23 +0000 (+0000) Subject: Syncronize filesystems to disk when suspending. Each mountpoint's vnodes X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=976e983900b26f1c1815971efe0ad0990654d735;p=openbsd 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. --- 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 * Copyright (c) 2005 Jordan Hargrave @@ -30,6 +30,8 @@ #include #include #include +#include +#include #ifdef HIBERNATE #include @@ -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 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 @@ -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 * @@ -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 * @@ -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); }