diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -400,12 +400,6 @@ */ uma_zone_t buf_zone; -/* - * Single global constant for BUF_WMESG, to avoid getting multiple references. - * buf_wmesg is referred from macros. - */ -const char *buf_wmesg = BUF_WMESG; - static int sysctl_runningspace(SYSCTL_HANDLER_ARGS) { @@ -1184,6 +1178,12 @@ return (v); } +/* + * Single global constant for BUF_WMESG, to avoid getting multiple + * references. + */ +static const char buf_wmesg[] = "bufwait"; + /* Initialize the buffer subsystem. Called before use of any buffers. */ void bufinit(void) @@ -1214,7 +1214,7 @@ bp->b_xflags = 0; bp->b_data = bp->b_kvabase = unmapped_buf; LIST_INIT(&bp->b_dep); - BUF_LOCKINIT(bp); + BUF_LOCKINIT(bp, buf_wmesg); bq_insert(&bqempty, bp, false); } @@ -1718,7 +1718,7 @@ if (freebufs == bd->bd_lofreebuffers) bufspace_daemon_wakeup(bd); - error = BUF_LOCK(bp, LK_EXCLUSIVE, NULL); + error = BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL); KASSERT(error == 0, ("%s: BUF_LOCK on free buf %p: %d.", __func__, bp, error)); (void)error; diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -5059,10 +5059,7 @@ */ if (vfs_busy(mp, MBF_NOWAIT) != 0) return (0); - if (vn_start_write(NULL, &mp, V_NOWAIT) != 0) { - vfs_unbusy(mp); - return (0); - } + VOP_UNLOCK(syncvp); save = curthread_pflags_set(TDP_SYNCIO); /* * The filesystem at hand may be idle with free vnodes stored in the @@ -5071,7 +5068,7 @@ vfs_periodic(mp, MNT_NOWAIT); error = VFS_SYNC(mp, MNT_LAZY); curthread_pflags_restore(save); - vn_finished_write(mp); + vn_lock(syncvp, LK_EXCLUSIVE | LK_RETRY); vfs_unbusy(mp); return (error); } diff --git a/sys/sys/buf.h b/sys/sys/buf.h --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -292,16 +292,14 @@ /* * Buffer locking */ -extern const char *buf_wmesg; /* Default buffer lock message */ -#define BUF_WMESG "bufwait" #include /* XXX for curthread */ #include /* * Initialize a lock. */ -#define BUF_LOCKINIT(bp) \ - lockinit(&(bp)->b_lock, PRIBIO + 4, buf_wmesg, 0, LK_NEW) +#define BUF_LOCKINIT(bp, wmesg) \ + lockinit(&(bp)->b_lock, PRIBIO + 4, wmesg, 0, LK_NEW) /* * * Get a lock sleeping non-interruptably until it becomes available. diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -179,7 +179,7 @@ pause("ffsupd", 1); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); vrele(vp); - if (VN_IS_DOOMED(vp)) + if (!IS_UFS(vp)) return (ENOENT); /* diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -1809,9 +1809,15 @@ VI_UNLOCK(devvp); return (0); } + + /* + * Use LK_SLEEPFAIL because sn might be freed under us while + * both devvp interlock and snaplk are not owned. + */ if (lockmgr(&sn->sn_lock, LK_INTERLOCK | LK_EXCLUSIVE | LK_SLEEPFAIL, VI_MTX(devvp)) != 0) goto retry; + TAILQ_FOREACH(ip, &sn->sn_head, i_nextsnap) { vp = ITOV(ip); if (DOINGSOFTDEP(vp)) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -13772,7 +13772,7 @@ vholdl(vp); vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY); VI_LOCK(vp); - if (vp->v_data != NULL && vp->v_usecount == 0) { + if (IS_UFS(vp) && vp->v_usecount == 0) { while ((vp->v_iflag & VI_OWEINACT) != 0) { error = vinactive(vp); if (error != 0 && error != ERELOOKUP) diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -2066,7 +2066,7 @@ * and respond to dead vnodes by returning ESTALE. */ VOP_LOCK(vp, vp_locked | LK_RETRY); - if (!VN_IS_DOOMED(vp)) + if (IS_UFS(vp)) return (0); /* diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h --- a/sys/ufs/ufs/inode.h +++ b/sys/ufs/ufs/inode.h @@ -247,6 +247,7 @@ } while (0) #define IS_SNAPSHOT(ip) ((ip)->i_flags & SF_SNAPSHOT) +#define IS_UFS(vp) ((vp)->v_data != NULL) /* * Structure used to pass around logical block paths generated by diff --git a/sys/ufs/ufs/ufs_bmap.c b/sys/ufs/ufs/ufs_bmap.c --- a/sys/ufs/ufs/ufs_bmap.c +++ b/sys/ufs/ufs/ufs_bmap.c @@ -217,14 +217,12 @@ * return a request for a zeroed out buffer if attempts * are made to read a BLK_NOCOPY or BLK_SNAP block. */ - if ((ip->i_flags & SF_SNAPSHOT) && DIP(ip, i_db[bn]) > 0 && + if (IS_SNAPSHOT(ip) && DIP(ip, i_db[bn]) > 0 && DIP(ip, i_db[bn]) < ump->um_seqinc) { *bnp = -1; } else if (*bnp == 0) { - if (ip->i_flags & SF_SNAPSHOT) - *bnp = blkptrtodb(ump, bn * ump->um_seqinc); - else - *bnp = -1; + *bnp = IS_SNAPSHOT(ip) ? blkptrtodb(ump, + bn * ump->um_seqinc) : -1; } else if (runp) { ufs2_daddr_t bnb = bn; for (++bn; bn < UFS_NDADDR && *runp < maxrun && @@ -320,13 +318,13 @@ * return a request for a zeroed out buffer if attempts are made * to read a BLK_NOCOPY or BLK_SNAP block. */ - if ((ip->i_flags & SF_SNAPSHOT) && daddr > 0 && daddr < ump->um_seqinc){ + if (IS_SNAPSHOT(ip) && daddr > 0 && daddr < ump->um_seqinc){ *bnp = -1; return (0); } *bnp = blkptrtodb(ump, daddr); if (*bnp == 0) { - if (ip->i_flags & SF_SNAPSHOT) + if (IS_SNAPSHOT(ip)) *bnp = blkptrtodb(ump, bn * ump->um_seqinc); else *bnp = -1; @@ -367,7 +365,7 @@ mp = vp->v_mount; ump = VFSTOUFS(mp); - if (vp->v_type != VREG || (ip->i_flags & SF_SNAPSHOT) != 0) + if (vp->v_type != VREG || IS_SNAPSHOT(ip)) return (EINVAL); if (*offp < 0 || *offp >= ip->i_size) return (ENXIO); diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -1245,8 +1245,7 @@ * drop its snapshot reference so that it will be reclaimed * when last open reference goes away. */ - if (ip != NULL && (ip->i_flags & SF_SNAPSHOT) != 0 && - ip->i_effnlink == 0) + if (ip != NULL && IS_SNAPSHOT(ip) && ip->i_effnlink == 0) UFS_SNAPGONE(ip); return (error); } @@ -1320,7 +1319,7 @@ * drop its snapshot reference so that it will be reclaimed * when last open reference goes away. */ - if ((oip->i_flags & SF_SNAPSHOT) != 0 && oip->i_effnlink == 0) + if (IS_SNAPSHOT(oip) && oip->i_effnlink == 0) UFS_SNAPGONE(oip); return (error); } diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -702,7 +702,7 @@ */ if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); - if ((ip->i_flags & SF_SNAPSHOT) != 0) + if (IS_SNAPSHOT(ip)) return (EPERM); break; default: @@ -726,7 +726,7 @@ vap->va_birthtime.tv_sec != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); - if ((ip->i_flags & SF_SNAPSHOT) != 0) + if (IS_SNAPSHOT(ip)) return (EPERM); error = vn_utimes_perm(vp, vap, cred, td); if (error != 0) @@ -754,8 +754,8 @@ if (vap->va_mode != (mode_t)VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); - if ((ip->i_flags & SF_SNAPSHOT) != 0 && (vap->va_mode & - (S_IXUSR | S_IWUSR | S_IXGRP | S_IWGRP | S_IXOTH | S_IWOTH))) + if (IS_SNAPSHOT(ip) && (vap->va_mode & (S_IXUSR | S_IWUSR | + S_IXGRP | S_IWGRP | S_IXOTH | S_IWOTH)) != 0) return (EPERM); error = ufs_chmod(vp, (int)vap->va_mode, cred, td); } @@ -1022,7 +1022,7 @@ error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0); if (ip->i_nlink <= 0) vp->v_vflag |= VV_NOSYNC; - if ((ip->i_flags & SF_SNAPSHOT) != 0) { + if (IS_SNAPSHOT(ip)) { /* * Avoid deadlock where another thread is trying to * update the inodeblock for dvp and is waiting on diff --git a/sys/vm/vm_pager.c b/sys/vm/vm_pager.c --- a/sys/vm/vm_pager.c +++ b/sys/vm/vm_pager.c @@ -489,6 +489,8 @@ BUF_UNLOCK(bp); } +static const char pbuf_wmesg[] = "pbufwait"; + static int pbuf_init(void *mem, int size, int flags) { @@ -498,7 +500,7 @@ if (bp->b_kvabase == NULL) return (ENOMEM); bp->b_kvasize = ptoa(PBUF_PAGES); - BUF_LOCKINIT(bp); + BUF_LOCKINIT(bp, pbuf_wmesg); LIST_INIT(&bp->b_dep); bp->b_rcred = bp->b_wcred = NOCRED; bp->b_xflags = 0;