Syncronize filesystems to disk when suspending. Each mountpoint's vnodes
authorderaadt <deraadt@openbsd.org>
Sat, 10 Feb 2018 05:24:23 +0000 (05:24 +0000)
committerderaadt <deraadt@openbsd.org>
Sat, 10 Feb 2018 05:24:23 +0000 (05:24 +0000)
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.

22 files changed:
sys/dev/acpi/acpi.c
sys/isofs/cd9660/cd9660_extern.h
sys/isofs/cd9660/cd9660_vfsops.c
sys/isofs/udf/udf_extern.h
sys/isofs/udf/udf_vfsops.c
sys/kern/vfs_subr.c
sys/kern/vfs_sync.c
sys/kern/vfs_syscalls.c
sys/kern/vfs_vops.c
sys/miscfs/fuse/fuse_vfsops.c
sys/msdosfs/msdosfs_vfsops.c
sys/msdosfs/msdosfsmount.h
sys/nfs/nfs_vfsops.c
sys/ntfs/ntfs_vfsops.c
sys/sys/file.h
sys/sys/mount.h
sys/sys/vnode.h
sys/ufs/ext2fs/ext2fs_extern.h
sys/ufs/ext2fs/ext2fs_vfsops.c
sys/ufs/ffs/ffs_extern.h
sys/ufs/ffs/ffs_softdep.c
sys/ufs/ffs/ffs_vfsops.c

index ea23d66..4e5fc3f 100644 (file)
@@ -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);
index 48b842a..8c4bebf 100644 (file)
@@ -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 *);
index efe2e4a..ac3df59 100644 (file)
@@ -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;
 {
index 07859f3..c48782c 100644 (file)
@@ -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 **);
index 56ef21f..8a0173d 100644 (file)
@@ -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);
 }
index 7311916..1e325fa 100644 (file)
@@ -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
 }
 
 /*
index 86fda88..bb8ee50 100644 (file)
@@ -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);
index 675a4d6..1edad24 100644 (file)
@@ -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;
                }
index f579134..42ba4ee 100644 (file)
@@ -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
index 7867ff6..7f7b044 100644 (file)
@@ -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);
index 67af60d..f2a7a5d 100644 (file)
@@ -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;
index dc892fe..23b5a65 100644 (file)
@@ -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 *);
index 65874a1..259b2f7 100644 (file)
@@ -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;
index 6ceac5b..9ad5ac1 100644 (file)
@@ -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);
index 23c2b86..ef27cd5 100644 (file)
@@ -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 {                             \
index fbed4bc..9ec04f6 100644 (file)
@@ -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 */
index 32a2d96..f113739 100644 (file)
@@ -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 */
index a0253a1..68c71ca 100644 (file)
@@ -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 *);
index 114285d..55cfacd 100644 (file)
@@ -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);
 }
 
index 45de572..0abe9d7 100644 (file)
@@ -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 *);
index f98dcd2..97b3d24 100644 (file)
@@ -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);
index 9492e50..874551b 100644 (file)
@@ -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);
 }