Put more struct vnode fields under splbio().
authorvisa <visa@openbsd.org>
Fri, 12 Aug 2022 14:30:52 +0000 (14:30 +0000)
committervisa <visa@openbsd.org>
Fri, 12 Aug 2022 14:30:52 +0000 (14:30 +0000)
Buffer cache related struct vnode fields can be accessed in interrupt
context. Be more consistent with the use of splbio().

OK mpi@

sys/kern/vfs_bio.c
sys/kern/vfs_subr.c
sys/msdosfs/msdosfs_vfsops.c
sys/nfs/nfs_vfsops.c
sys/nfs/nfs_vnops.c
sys/sys/vnode.h
sys/ufs/ext2fs/ext2fs_inode.c
sys/ufs/ext2fs/ext2fs_vfsops.c
sys/ufs/ffs/ffs_vfsops.c

index 1e29dfc..7ff46e1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vfs_bio.c,v 1.208 2021/12/12 09:14:59 visa Exp $      */
+/*     $OpenBSD: vfs_bio.c,v 1.209 2022/08/12 14:30:52 visa Exp $      */
 /*     $NetBSD: vfs_bio.c,v 1.44 1996/06/11 11:15:36 pk Exp $  */
 
 /*
@@ -1554,7 +1554,10 @@ bufcache_getcleanbuf(int cachenum, int discard)
 
 
 void
-discard_buffer(struct buf *bp) {
+discard_buffer(struct buf *bp)
+{
+       splassert(IPL_BIO);
+
        bufcache_take(bp);
        if (bp->b_vp) {
                RBT_REMOVE(buf_rb_bufs,
index 13c7089..4ace1ad 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vfs_subr.c,v 1.315 2022/03/27 16:19:39 semarie Exp $  */
+/*     $OpenBSD: vfs_subr.c,v 1.316 2022/08/12 14:30:52 visa Exp $     */
 /*     $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $   */
 
 /*
@@ -662,16 +662,16 @@ vget(struct vnode *vp, int flags)
        }
        mtx_leave(&vnode_mtx);
 
+       s = splbio();
        onfreelist = vp->v_bioflag & VBIOONFREELIST;
        if (vp->v_usecount == 0 && onfreelist) {
-               s = splbio();
                if (vp->v_holdcnt > 0)
                        TAILQ_REMOVE(&vnode_hold_list, vp, v_freelist);
                else
                        TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
                vp->v_bioflag &= ~VBIOONFREELIST;
-               splx(s);
        }
+       splx(s);
 
        vp->v_usecount++;
        if (flags & LK_TYPE_MASK) {
@@ -749,6 +749,7 @@ void
 vput(struct vnode *vp)
 {
        struct proc *p = curproc;
+       int s;
 
 #ifdef DIAGNOSTIC
        if (vp == NULL)
@@ -777,8 +778,10 @@ vput(struct vnode *vp)
 
        VOP_INACTIVE(vp, p);
 
+       s = splbio();
        if (vp->v_usecount == 0 && !(vp->v_bioflag & VBIOONFREELIST))
                vputonfreelist(vp);
+       splx(s);
 }
 
 /*
@@ -790,6 +793,7 @@ int
 vrele(struct vnode *vp)
 {
        struct proc *p = curproc;
+       int s;
 
 #ifdef DIAGNOSTIC
        if (vp == NULL)
@@ -822,8 +826,10 @@ vrele(struct vnode *vp)
 
        VOP_INACTIVE(vp, p);
 
+       s = splbio();
        if (vp->v_usecount == 0 && !(vp->v_bioflag & VBIOONFREELIST))
                vputonfreelist(vp);
+       splx(s);
        return (1);
 }
 
@@ -831,6 +837,10 @@ vrele(struct vnode *vp)
 void
 vhold(struct vnode *vp)
 {
+       int s;
+
+       s = splbio();
+
        /*
         * If it is on the freelist and the hold count is currently
         * zero, move it to the hold list.
@@ -841,12 +851,18 @@ vhold(struct vnode *vp)
                TAILQ_INSERT_TAIL(&vnode_hold_list, vp, v_freelist);
        }
        vp->v_holdcnt++;
+
+       splx(s);
 }
 
 /* Lose interest in a vnode. */
 void
 vdrop(struct vnode *vp)
 {
+       int s;
+
+       s = splbio();
+
 #ifdef DIAGNOSTIC
        if (vp->v_holdcnt == 0)
                panic("vdrop: zero holdcnt");
@@ -863,6 +879,8 @@ vdrop(struct vnode *vp)
                TAILQ_REMOVE(&vnode_hold_list, vp, v_freelist);
                TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
        }
+
+       splx(s);
 }
 
 /*
@@ -909,6 +927,7 @@ vflush_vnode(struct vnode *vp, void *arg)
 {
        struct vflush_args *va = arg;
        struct proc *p = curproc;
+       int empty, s;
 
        if (vp == va->skipvp) {
                return (0);
@@ -958,8 +977,11 @@ vflush_vnode(struct vnode *vp, void *arg)
         * XXX Might be nice to check per-fs "inode" flags, but
         * generally the filesystem is sync'd already, right?
         */
-       if ((va->flags & IGNORECLEAN) &&
-           LIST_EMPTY(&vp->v_dirtyblkhd))
+       s = splbio();
+       empty = (va->flags & IGNORECLEAN) && LIST_EMPTY(&vp->v_dirtyblkhd);
+       splx(s);
+
+       if (empty)
                return (0);
 
 #ifdef DEBUG_SYSCTL
@@ -992,6 +1014,7 @@ void
 vclean(struct vnode *vp, int flags, struct proc *p)
 {
        int active, do_wakeup = 0;
+       int s;
 
        /*
         * Check to see if the vnode is in use.
@@ -1066,9 +1089,11 @@ vclean(struct vnode *vp, int flags, struct proc *p)
        if (active) {
                vp->v_usecount--;
                if (vp->v_usecount == 0) {
+                       s = splbio();
                        if (vp->v_holdcnt > 0)
                                panic("vclean: not clean");
                        vputonfreelist(vp);
+                       splx(s);
                }
        }
        cache_purge(vp);
@@ -1125,6 +1150,7 @@ vgonel(struct vnode *vp, struct proc *p)
 {
        struct vnode *vq;
        struct vnode *vx;
+       int s;
 
        KASSERT(vp->v_uvcount == 0);
 
@@ -1192,12 +1218,9 @@ vgonel(struct vnode *vp, struct proc *p)
         * Move onto the free list, unless we were called from
         * getnewvnode and we're not on any free list
         */
+       s = splbio();
        if (vp->v_usecount == 0 &&
            (vp->v_bioflag & VBIOONFREELIST)) {
-               int s;
-
-               s = splbio();
-
                if (vp->v_holdcnt > 0)
                        panic("vgonel: not clean");
 
@@ -1205,8 +1228,8 @@ vgonel(struct vnode *vp, struct proc *p)
                        TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
                        TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
                }
-               splx(s);
        }
+       splx(s);
 }
 
 /*
index 543854c..0de3766 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: msdosfs_vfsops.c,v 1.95 2021/11/13 18:18:59 kn Exp $  */
+/*     $OpenBSD: msdosfs_vfsops.c,v 1.96 2022/08/12 14:30:52 visa Exp $        */
 /*     $NetBSD: msdosfs_vfsops.c,v 1.48 1997/10/18 02:54:57 briggs Exp $       */
 
 /*-
@@ -640,16 +640,22 @@ int
 msdosfs_sync_vnode(struct vnode *vp, void *arg)
 {
        struct msdosfs_sync_arg *msa = arg;
-       int error;
        struct denode *dep;
+       int error;
+       int s, skip = 0;
 
        dep = VTODE(vp);
+       s = splbio();
        if (vp->v_type == VNON ||
            ((dep->de_flag & (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0
              && LIST_EMPTY(&vp->v_dirtyblkhd)) ||
            msa->waitfor == MNT_LAZY) {
-               return (0);
+               skip = 1;
        }
+       splx(s);
+
+       if (skip)
+               return (0);
 
        if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT))
                return (0);
index d0a7bcf..5b06158 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nfs_vfsops.c,v 1.126 2021/01/02 02:41:42 cheloha Exp $        */
+/*     $OpenBSD: nfs_vfsops.c,v 1.127 2022/08/12 14:30:53 visa Exp $   */
 /*     $NetBSD: nfs_vfsops.c,v 1.46.4.1 1996/05/25 22:40:35 fvdl Exp $ */
 
 /*
@@ -793,7 +793,8 @@ int
 nfs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p)
 {
        struct vnode *vp;
-       int error, allerror = 0;
+       int allerror = 0;
+       int empty, error, s;
 
        /*
         * Don't traverse the vnode list if we want to skip all of them.
@@ -812,7 +813,12 @@ loop:
                 */
                if (vp->v_mount != mp)
                        goto loop;
-               if (VOP_ISLOCKED(vp) || LIST_EMPTY(&vp->v_dirtyblkhd))
+               if (VOP_ISLOCKED(vp))
+                       continue;
+               s = splbio();
+               empty = LIST_EMPTY(&vp->v_dirtyblkhd);
+               splx(s);
+               if (empty)
                        continue;
                if (vget(vp, LK_EXCLUSIVE))
                        goto loop;
index 3cc87e3..8e10c52 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nfs_vnops.c,v 1.189 2022/06/26 05:20:42 visa Exp $    */
+/*     $OpenBSD: nfs_vnops.c,v 1.190 2022/08/12 14:30:53 visa Exp $    */
 /*     $NetBSD: nfs_vnops.c,v 1.62.4.1 1996/07/08 20:26:52 jtc Exp $   */
 
 /*
@@ -2849,7 +2849,7 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct proc *p,
        struct nfsmount *nmp = VFSTONFS(vp->v_mount);
        uint64_t slptimeo = INFSLP;
        int s, error = 0, slpflag = 0, retv, bvecpos;
-       int passone = 1;
+       int dirty, passone = 1;
        u_quad_t off = (u_quad_t)-1, endoff = 0, toff;
 #ifndef NFS_COMMITBVECSIZ
 #define NFS_COMMITBVECSIZ      20
@@ -2982,8 +2982,8 @@ loop:
  loop2:
                s = splbio();
                error = vwaitforio(vp, slpflag, "nfs_fsync", slptimeo);
-               splx(s);
                if (error) {
+                       splx(s);
                        if (nfs_sigintr(nmp, NULL, p))
                                return (EINTR);
                        if (slpflag == PCATCH) {
@@ -2992,8 +2992,9 @@ loop:
                        }
                        goto loop2;
                }
-
-               if (!LIST_EMPTY(&vp->v_dirtyblkhd) && commit) {
+               dirty = (!LIST_EMPTY(&vp->v_dirtyblkhd) && commit);
+               splx(s);
+               if (dirty) {
 #if 0
                        vprint("nfs_fsync: dirty", vp);
 #endif
index a5adb99..c9bb267 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vnode.h,v 1.166 2022/06/26 05:20:42 visa Exp $        */
+/*     $OpenBSD: vnode.h,v 1.167 2022/08/12 14:30:53 visa Exp $        */
 /*     $NetBSD: vnode.h,v 1.38 1996/02/29 20:59:05 cgd Exp $   */
 
 /*
@@ -104,18 +104,17 @@ struct vnode {
        u_int   v_writecount;           /* reference count of writers */
        u_int   v_lockcount;            /* [V] # threads waiting on lock */
 
-       /* Flags that can be read/written in interrupts */
-       u_int   v_bioflag;
-       u_int   v_holdcnt;                      /* buffer references */
+       u_int   v_bioflag;              /* [B] flags accessed in interrupts */
+       u_int   v_holdcnt;              /* [B] buffer references */
        u_int   v_id;                           /* capability identifier */
        struct  mount *v_mount;                 /* ptr to vfs we are in */
-       TAILQ_ENTRY(vnode) v_freelist;          /* vnode freelist */
+       TAILQ_ENTRY(vnode) v_freelist;  /* [B] vnode freelist */
        TAILQ_ENTRY(vnode) v_mntvnodes;         /* vnodes for mount point */
-       struct  buf_rb_bufs v_bufs_tree;        /* lookup of all bufs */
-       struct  buflists v_cleanblkhd;          /* clean blocklist head */
-       struct  buflists v_dirtyblkhd;          /* dirty blocklist head */
+       struct  buf_rb_bufs v_bufs_tree;/* [B] lookup of all bufs */
+       struct  buflists v_cleanblkhd;  /* [B] clean blocklist head */
+       struct  buflists v_dirtyblkhd;  /* [B] dirty blocklist head */
        u_int   v_numoutput;            /* [B] num of writes in progress */
-       LIST_ENTRY(vnode) v_synclist;           /* vnode with dirty buffers */
+       LIST_ENTRY(vnode) v_synclist;   /* [B] vnode with dirty buffers */
        union {
                struct mount    *vu_mountedhere;/* ptr to mounted vfs (VDIR) */
                struct socket   *vu_socket;     /* unix ipc (VSOCK) */
index 5c76a59..2962628 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ext2fs_inode.c,v 1.65 2021/12/12 09:14:59 visa Exp $  */
+/*     $OpenBSD: ext2fs_inode.c,v 1.66 2022/08/12 14:30:53 visa Exp $  */
 /*     $NetBSD: ext2fs_inode.c,v 1.24 2001/06/19 12:59:18 wiz Exp $    */
 
 /*
@@ -387,10 +387,15 @@ done:
        for (i = 0; i < NDADDR; i++)
                if (newblks[i] != oip->i_e2fs_blocks[i])
                        panic("ext2fs_truncate2");
-       if (length == 0 &&
-           (!LIST_EMPTY(&ovp->v_cleanblkhd) ||
-            !LIST_EMPTY(&ovp->v_dirtyblkhd)))
-               panic("ext2fs_truncate3");
+       if (length == 0) {
+               int s;
+
+               s = splbio();
+               if (!LIST_EMPTY(&ovp->v_cleanblkhd) ||
+                   !LIST_EMPTY(&ovp->v_dirtyblkhd))
+                       panic("ext2fs_truncate3");
+               splx(s);
+       }
 #endif /* DIAGNOSTIC */
        /*
         * Put back the real size.
index 371ca53..af3f0a9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ext2fs_vfsops.c,v 1.116 2021/10/04 08:11:02 claudio Exp $     */
+/*     $OpenBSD: ext2fs_vfsops.c,v 1.117 2022/08/12 14:30:53 visa Exp $        */
 /*     $NetBSD: ext2fs_vfsops.c,v 1.1 1997/06/11 09:34:07 bouyer Exp $ */
 
 /*
@@ -713,6 +713,7 @@ ext2fs_sync_vnode(struct vnode *vp, void *args)
        struct ext2fs_sync_args *esa = args;
        struct inode *ip;
        int error, nlink0 = 0;
+       int s, skip = 0;
 
        if (vp->v_type == VNON)
                return (0);
@@ -722,10 +723,15 @@ ext2fs_sync_vnode(struct vnode *vp, void *args)
        if (ip->i_e2fs_nlink == 0)
                nlink0 = 1;
 
+       s = splbio();
        if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
            LIST_EMPTY(&vp->v_dirtyblkhd)) {
-               goto end;
+               skip = 1;
        }
+       splx(s);
+
+       if (skip)
+               goto end;
 
        if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT)) {
                esa->inflight = MIN(esa->inflight+1, 65536);
index b513a27..730a36b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ffs_vfsops.c,v 1.192 2021/10/20 06:35:39 semarie Exp $        */
+/*     $OpenBSD: ffs_vfsops.c,v 1.193 2022/08/12 14:30:53 visa Exp $   */
 /*     $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */
 
 /*
@@ -1159,6 +1159,7 @@ ffs_sync_vnode(struct vnode *vp, void *arg)
        struct ffs_sync_args *fsa = arg;
        struct inode *ip;
        int error, nlink0 = 0;
+       int s, skip = 0;
 
        if (vp->v_type == VNON)
                return (0);
@@ -1177,11 +1178,16 @@ ffs_sync_vnode(struct vnode *vp, void *arg)
        if (ip->i_effnlink == 0)
                nlink0 = 1;
 
+       s = splbio();
        if ((ip->i_flag &
            (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
            LIST_EMPTY(&vp->v_dirtyblkhd)) {
-               goto end;
+               skip = 1;
        }
+       splx(s);
+
+       if (skip)
+               goto end;
 
        if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT)) {
                fsa->inflight = MIN(fsa->inflight+1, 65536);