When doing cleanup of excessive buffers in bdwrite (see kern/vfs_bio.c

delta 1.371) we must ensure that we do not get ourselves into a
recursive trap endlessly trying to clean up after ourselves.

Reported by:	Attila Nagy <bra@fsn.hu>
Sponsored by:   DARPA & NAI Labs.
This commit is contained in:
Kirk McKusick 2003-02-25 23:59:09 +00:00
parent 74f3809a19
commit 7e734c4149

View File

@ -130,6 +130,9 @@ SYSCTL_INT(_vfs, OID_AUTO, dirtybufferflushes, CTLFLAG_RW, &dirtybufferflushes,
static int altbufferflushes;
SYSCTL_INT(_vfs, OID_AUTO, altbufferflushes, CTLFLAG_RW, &altbufferflushes,
0, "Number of fsync flushes to limit dirty buffers");
static int recursiveflushes;
SYSCTL_INT(_vfs, OID_AUTO, recursiveflushes, CTLFLAG_RW, &recursiveflushes,
0, "Number of flushes skipped due to being recursive");
static int numdirtybuffers;
SYSCTL_INT(_vfs, OID_AUTO, numdirtybuffers, CTLFLAG_RD, &numdirtybuffers, 0,
"Number of buffers that are dirty (has unwritten changes) at the moment");
@ -1021,11 +1024,14 @@ bdwrite(struct buf * bp)
* If we have too many dirty buffers, don't create any more.
* If we are wildly over our limit, then force a complete
* cleanup. Otherwise, just keep the situation from getting
* out of control.
* out of control. Note that we have to avoid a recursive
* disaster and not try to clean up after our own cleanup!
*/
vp = bp->b_vp;
VI_LOCK(vp);
if (vp != NULL && vp->v_dirtybufcnt > dirtybufthresh + 10) {
if (td->td_proc->p_flag & P_COWINPROGRESS) {
recursiveflushes++;
} else if (vp != NULL && vp->v_dirtybufcnt > dirtybufthresh + 10) {
VI_UNLOCK(vp);
(void) VOP_FSYNC(vp, td->td_ucred, MNT_NOWAIT, td);
VI_LOCK(vp);