diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index f1b9be6..cc9bd11 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -557,6 +557,7 @@ bufinit(void) bp->b_qindex = QUEUE_EMPTY; bp->b_vflags = 0; bp->b_xflags = 0; + bp->b_waiters = 0; LIST_INIT(&bp->b_dep); BUF_LOCKINIT(bp); TAILQ_INSERT_TAIL(&bufqueues[QUEUE_EMPTY], bp, b_freelist); @@ -1195,7 +1196,7 @@ brelse(struct buf *bp) if (bp->b_bufsize) allocbuf(bp, 0); if (bp->b_vp) - brelvp(bp); + (void) brelvp(bp); } } @@ -1337,7 +1338,7 @@ brelse(struct buf *bp) if (bp->b_bufsize != 0) allocbuf(bp, 0); if (bp->b_vp != NULL) - brelvp(bp); + (void) brelvp(bp); } if (BUF_LOCKRECURSED(bp)) { @@ -1401,7 +1402,7 @@ brelse(struct buf *bp) if (bp->b_flags & B_DELWRI) bundirty(bp); if (bp->b_vp) - brelvp(bp); + (void) brelvp(bp); } /* @@ -1569,7 +1570,7 @@ vfs_vmio_release(struct buf *bp) bp->b_npages = 0; bp->b_flags &= ~B_VMIO; if (bp->b_vp) - brelvp(bp); + (void) brelvp(bp); } /* @@ -1706,6 +1707,7 @@ getnewbuf(int slpflag, int slptimeo, int size, int maxsize) struct buf *nbp; int defrag = 0; int nqindex; + int waiters = 0; static int flushingbufs; /* @@ -1844,7 +1846,7 @@ restart: vfs_vmio_release(bp); } if (bp->b_vp) - brelvp(bp); + waiters = brelvp(bp); } /* @@ -1913,7 +1915,7 @@ restart: * Notify any waiters for the buffer lock about * identity change by freeing the buffer. */ - if (qindex == QUEUE_CLEAN && BUF_LOCKWAITERS(bp) > 0) { + if (qindex == QUEUE_CLEAN && waiters > 0) { bp->b_flags |= B_INVAL; bfreekva(bp); brelse(bp); diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 176be13..f6e1a59 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1525,11 +1525,12 @@ bgetvp(struct vnode *vp, struct buf *bp) /* * Disassociate a buffer from a vnode. */ -void +int brelvp(struct buf *bp) { struct bufobj *bo; struct vnode *vp; + int waiters; CTR3(KTR_BUF, "brelvp(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags); KASSERT(bp->b_vp != NULL, ("brelvp: NULL")); @@ -1554,7 +1555,10 @@ brelvp(struct buf *bp) bp->b_flags &= ~B_NEEDSGIANT; bp->b_vp = NULL; bp->b_bufobj = NULL; + waiters = bp->b_waiters; vdropl(vp); + + return (waiters); } /* diff --git a/sys/sys/buf.h b/sys/sys/buf.h index 486c73c..58e5ad7 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -139,6 +139,7 @@ struct buf { void *b_fsprivate2; void *b_fsprivate3; int b_pin_count; + int b_waiters; /* (V) waiters counter */ }; #define b_object b_bufobj->bo_object @@ -266,15 +267,41 @@ extern const char *buf_wmesg; /* Default buffer lock message */ * * Get a lock sleeping non-interruptably until it becomes available. */ -#define BUF_LOCK(bp, locktype, interlock) \ - (lockmgr(&(bp)->b_lock, (locktype), (interlock))) +static __inline int +BUF_LOCK(struct buf *bp, int locktype, struct mtx *interlock); +static __inline int +BUF_LOCK(struct buf *bp, int locktype, struct mtx *interlock) +{ + int res; + + if (locktype & LK_INTERLOCK) + bp->b_waiters++; + res = lockmgr(&bp->b_lock, locktype, interlock); + if (locktype & LK_INTERLOCK) + bp->b_waiters--; + return (res); +} /* * Get a lock sleeping with specified interruptably and timeout. */ -#define BUF_TIMELOCK(bp, locktype, interlock, wmesg, catch, timo) \ - (lockmgr_args(&(bp)->b_lock, (locktype) | LK_TIMELOCK, \ - (interlock), (wmesg), (PRIBIO + 4) | (catch), (timo))) +static __inline int +BUF_TIMELOCK(struct buf *bp, int locktype, struct mtx *interlock, + const char *wmesg, int catch, int timo); +static __inline int +BUF_TIMELOCK(struct buf *bp, int locktype, struct mtx *interlock, + const char *wmesg, int catch, int timo) +{ + int res; + + if (locktype & LK_INTERLOCK) + bp->b_waiters++; + res = lockmgr_args(&bp->b_lock, locktype | LK_TIMELOCK, interlock, + wmesg, (PRIBIO + 4) | catch, timo); + if (locktype & LK_INTERLOCK) + bp->b_waiters--; + return (res); +} /* * Release a lock. Only the acquiring process may free the lock unless @@ -351,16 +378,6 @@ BUF_KERNPROC(struct buf *bp) } #endif -/* - * Find out the number of waiters on a lock. - */ -static __inline int BUF_LOCKWAITERS(struct buf *); -static __inline int -BUF_LOCKWAITERS(struct buf *bp) -{ - return (lockwaiters(&bp->b_lock)); -} - #endif /* _KERNEL */ struct buf_queue_head { @@ -516,7 +533,7 @@ void vfs_unbusy_pages(struct buf *); int vmapbuf(struct buf *); void vunmapbuf(struct buf *); void relpbuf(struct buf *, int *); -void brelvp(struct buf *); +int brelvp(struct buf *); void bgetvp(struct vnode *, struct buf *); void pbgetbo(struct bufobj *bo, struct buf *bp); void pbgetvp(struct vnode *, struct buf *);