summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorattilio <attilio@FreeBSD.org>2008-03-28 12:30:12 +0000
committerattilio <attilio@FreeBSD.org>2008-03-28 12:30:12 +0000
commit7e107a0c8ce6820c1a2604de4575a1551b907341 (patch)
tree9d06a4e3f60083aa0a6dd748b98e5d47ee052b37
parent3d7f9d1b14e3b0a60532dcf7644a09862d4af9ed (diff)
downloadFreeBSD-src-7e107a0c8ce6820c1a2604de4575a1551b907341.zip
FreeBSD-src-7e107a0c8ce6820c1a2604de4575a1551b907341.tar.gz
b_waiters cannot be adequately protected by the interlock because it is
dropped after the call to lockmgr() so just revert this approach using something similar to the precedent one: BUF_LOCKWAITERS() just checks if there are waiters (not the actual number of them) and it is based on newly introduced lockmgr_waiters() which returns if the lockmgr has waiters or not. The name has been choosen differently by old lockwaiters() in order to not confuse them. KPI results enriched by this commit so __FreeBSD_version bumping and manpage update will be happening soon. 'struct buf' also changes, so kernel ABI is disturbed. Bug found by: jeff Approved by: jeff, kib
-rw-r--r--sys/kern/vfs_bio.c14
-rw-r--r--sys/kern/vfs_subr.c6
-rw-r--r--sys/sys/buf.h54
-rw-r--r--sys/sys/lockmgr.h2
4 files changed, 24 insertions, 52 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index cc04f37..a1725be 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -544,7 +544,6 @@ 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);
@@ -1183,7 +1182,7 @@ brelse(struct buf *bp)
if (bp->b_bufsize)
allocbuf(bp, 0);
if (bp->b_vp)
- (void) brelvp(bp);
+ brelvp(bp);
}
}
@@ -1324,7 +1323,7 @@ brelse(struct buf *bp)
if (bp->b_bufsize != 0)
allocbuf(bp, 0);
if (bp->b_vp != NULL)
- (void) brelvp(bp);
+ brelvp(bp);
}
if (BUF_LOCKRECURSED(bp)) {
@@ -1388,7 +1387,7 @@ brelse(struct buf *bp)
if (bp->b_flags & B_DELWRI)
bundirty(bp);
if (bp->b_vp)
- (void) brelvp(bp);
+ brelvp(bp);
}
/*
@@ -1555,7 +1554,7 @@ vfs_vmio_release(struct buf *bp)
bp->b_npages = 0;
bp->b_flags &= ~B_VMIO;
if (bp->b_vp)
- (void) brelvp(bp);
+ brelvp(bp);
}
/*
@@ -1693,7 +1692,6 @@ getnewbuf(int slpflag, int slptimeo, int size, int maxsize)
struct buf *nbp;
int defrag = 0;
int nqindex;
- int waiters = 0;
static int flushingbufs;
/*
@@ -1832,7 +1830,7 @@ restart:
vfs_vmio_release(bp);
}
if (bp->b_vp)
- waiters = brelvp(bp);
+ brelvp(bp);
}
/*
@@ -1901,7 +1899,7 @@ restart:
* Notify any waiters for the buffer lock about
* identity change by freeing the buffer.
*/
- if (qindex == QUEUE_CLEAN && waiters > 0) {
+ if (qindex == QUEUE_CLEAN && BUF_LOCKWAITERS(bp)) {
bp->b_flags |= B_INVAL;
bfreekva(bp);
brelse(bp);
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index b3bd6f6..84de803 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1527,12 +1527,11 @@ bgetvp(struct vnode *vp, struct buf *bp)
/*
* Disassociate a buffer from a vnode.
*/
-int
+void
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"));
@@ -1557,11 +1556,8 @@ brelvp(struct buf *bp)
bp->b_flags &= ~B_NEEDSGIANT;
bp->b_vp = NULL;
bp->b_bufobj = NULL;
- waiters = bp->b_waiters;
BO_UNLOCK(bo);
vdrop(vp);
-
- return (waiters);
}
/*
diff --git a/sys/sys/buf.h b/sys/sys/buf.h
index d735fb7..e05b20c 100644
--- a/sys/sys/buf.h
+++ b/sys/sys/buf.h
@@ -139,7 +139,6 @@ 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
@@ -267,38 +266,18 @@ extern const char *buf_wmesg; /* Default buffer lock message */
*
* Get a lock sleeping non-interruptably until it becomes available.
*/
-static __inline int
-_BUF_LOCK(struct buf *bp, int locktype, struct mtx *interlock, char *file,
- int line)
-{
- int res;
-
- if (locktype & LK_INTERLOCK)
- bp->b_waiters++;
- res = _lockmgr_args(&bp->b_lock, locktype, interlock, LK_WMESG_DEFAULT,
- LK_PRIO_DEFAULT, LK_TIMO_DEFAULT, file, line);
- if (locktype & LK_INTERLOCK)
- bp->b_waiters--;
- return (res);
-}
+#define BUF_LOCK(bp, locktype, interlock) \
+ _lockmgr_args(&(bp)->b_lock, (locktype), (interlock), \
+ LK_WMESG_DEFAULT, LK_PRIO_DEFAULT, LK_TIMO_DEFAULT, \
+ LOCK_FILE, LOCK_LINE)
/*
* Get a lock sleeping with specified interruptably and timeout.
*/
-static __inline int
-_BUF_TIMELOCK(struct buf *bp, int locktype, struct mtx *interlock,
- const char *wmesg, int catch, int timo, char *file, int line)
-{
- int res;
-
- if (locktype & LK_INTERLOCK)
- bp->b_waiters++;
- res = _lockmgr_args(&bp->b_lock, locktype | LK_TIMELOCK, interlock,
- wmesg, (PRIBIO + 4) | catch, timo, file, line);
- if (locktype & LK_INTERLOCK)
- bp->b_waiters--;
- return (res);
-}
+#define BUF_TIMELOCK(bp, locktype, interlock, wmesg, catch, timo) \
+ _lockmgr_args(&(bp)->b_lock, (locktype) | LK_TIMELOCK, \
+ (interlock), (wmesg), (PRIBIO + 4) | (catch), (timo), \
+ LOCK_FILE, LOCK_LINE)
/*
* Release a lock. Only the acquiring process may free the lock unless
@@ -331,15 +310,6 @@ _BUF_TIMELOCK(struct buf *bp, int locktype, struct mtx *interlock,
lockdestroy(&(bp)->b_lock)
/*
- * Use macro wrappers in order to exploit consumers tracking.
- */
-#define BUF_LOCK(bp, locktype, interlock) \
- _BUF_LOCK((bp), (locktype), (interlock), LOCK_FILE, LOCK_LINE)
-#define BUF_TIMELOCK(bp, locktype, interlock, wmesg, catch, timo) \
- _BUF_TIMELOCK((bp), (locktype), (interlock), (wmesg), (catch), \
- (timo), LOCK_FILE, LOCK_LINE)
-
-/*
* Buffer lock assertions.
*/
#if defined(INVARIANTS) && defined(INVARIANT_SUPPORT)
@@ -373,6 +343,12 @@ _BUF_TIMELOCK(struct buf *bp, int locktype, struct mtx *interlock,
_lockmgr_disown(&(bp)->b_lock, LOCK_FILE, LOCK_LINE)
#endif
+/*
+ * Find out if the lock has waiters or not.
+ */
+#define BUF_LOCKWAITERS(bp) \
+ lockmgr_waiters(&(bp)->b_lock)
+
#endif /* _KERNEL */
struct buf_queue_head {
@@ -528,7 +504,7 @@ void vfs_unbusy_pages(struct buf *);
int vmapbuf(struct buf *);
void vunmapbuf(struct buf *);
void relpbuf(struct buf *, int *);
-int brelvp(struct buf *);
+void brelvp(struct buf *);
void bgetvp(struct vnode *, struct buf *);
void pbgetbo(struct bufobj *bo, struct buf *bp);
void pbgetvp(struct vnode *, struct buf *);
diff --git a/sys/sys/lockmgr.h b/sys/sys/lockmgr.h
index 1b89355..9e2fe59 100644
--- a/sys/sys/lockmgr.h
+++ b/sys/sys/lockmgr.h
@@ -225,6 +225,8 @@ int lockstatus(struct lock *);
LOCK_FILE, LOCK_LINE)
#define lockmgr_recursed(lkp) \
((lkp)->lk_exclusivecount > 1)
+#define lockmgr_waiters(lkp) \
+ ((lkp)->lk_waitcount != 0)
#ifdef INVARIANTS
#define lockmgr_assert(lkp, what) \
_lockmgr_assert((lkp), (what), LOCK_FILE, LOCK_LINE)
OpenPOWER on IntegriCloud