summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_lock.c15
-rw-r--r--sys/kern/vfs_bio.c11
-rw-r--r--sys/sys/buf.h11
-rw-r--r--sys/sys/lockmgr.h1
4 files changed, 38 insertions, 0 deletions
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c
index c0b929a..32b43b8 100644
--- a/sys/kern/kern_lock.c
+++ b/sys/kern/kern_lock.c
@@ -566,6 +566,21 @@ lockcount(lkp)
}
/*
+ * Determine the number of waiters on a lock.
+ */
+int
+lockwaiters(lkp)
+ struct lock *lkp;
+{
+ int count;
+
+ mtx_lock(lkp->lk_interlock);
+ count = lkp->lk_waitcount;
+ mtx_unlock(lkp->lk_interlock);
+ return (count);
+}
+
+/*
* Print out information about state of a lock. Used by VOP_PRINT
* routines to display status about contained locks.
*/
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 37ef552..904e84c 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -1890,6 +1890,17 @@ restart:
}
/*
+ * Notify any waiters for the buffer lock about
+ * identity change by freeing the buffer.
+ */
+ if (qindex == QUEUE_CLEAN && BUF_LOCKWAITERS(bp) > 0) {
+ bp->b_flags |= B_INVAL;
+ bfreekva(bp);
+ brelse(bp);
+ goto restart;
+ }
+
+ /*
* If we are overcomitted then recover the buffer and its
* KVM space. This occurs in rare situations when multiple
* processes are blocked in getnewbuf() or allocbuf().
diff --git a/sys/sys/buf.h b/sys/sys/buf.h
index afa3e23..359be84 100644
--- a/sys/sys/buf.h
+++ b/sys/sys/buf.h
@@ -371,6 +371,17 @@ BUF_REFCNT(struct buf *bp)
return ret;
}
+
+/*
+ * 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 {
diff --git a/sys/sys/lockmgr.h b/sys/sys/lockmgr.h
index dd0eed9..9c9b59b 100644
--- a/sys/sys/lockmgr.h
+++ b/sys/sys/lockmgr.h
@@ -203,6 +203,7 @@ void transferlockers(struct lock *, struct lock *);
void lockmgr_printinfo(struct lock *);
int lockstatus(struct lock *, struct thread *);
int lockcount(struct lock *);
+int lockwaiters(struct lock *);
#ifdef DDB
int lockmgr_chain(struct thread *td, struct thread **ownerp);
#endif
OpenPOWER on IntegriCloud