If the buffer lock has waiters after the buffer has changed identity then
getnewbuf() needs to drop the buffer in order to wake waiters that might sleep on the buffer in the context of the old identity.
This commit is contained in:
parent
2eb6639bf4
commit
04aa807cb6
@ -565,6 +565,21 @@ lockcount(lkp)
|
|||||||
return (count);
|
return (count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* Print out information about state of a lock. Used by VOP_PRINT
|
||||||
* routines to display status about contained locks.
|
* routines to display status about contained locks.
|
||||||
|
@ -1889,6 +1889,17 @@ getnewbuf(int slpflag, int slptimeo, int size, int maxsize)
|
|||||||
goto restart;
|
goto 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
|
* If we are overcomitted then recover the buffer and its
|
||||||
* KVM space. This occurs in rare situations when multiple
|
* KVM space. This occurs in rare situations when multiple
|
||||||
|
@ -371,6 +371,17 @@ BUF_REFCNT(struct buf *bp)
|
|||||||
return ret;
|
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 */
|
#endif /* _KERNEL */
|
||||||
|
|
||||||
struct buf_queue_head {
|
struct buf_queue_head {
|
||||||
|
@ -203,6 +203,7 @@ void transferlockers(struct lock *, struct lock *);
|
|||||||
void lockmgr_printinfo(struct lock *);
|
void lockmgr_printinfo(struct lock *);
|
||||||
int lockstatus(struct lock *, struct thread *);
|
int lockstatus(struct lock *, struct thread *);
|
||||||
int lockcount(struct lock *);
|
int lockcount(struct lock *);
|
||||||
|
int lockwaiters(struct lock *);
|
||||||
#ifdef DDB
|
#ifdef DDB
|
||||||
int lockmgr_chain(struct thread *td, struct thread **ownerp);
|
int lockmgr_chain(struct thread *td, struct thread **ownerp);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user