Do not allow creation of the dirty buffers for the dead buffer

objects, i.e. for buffer objects which vnode was reclaimed.  Buffer
cache cannot write such buffers.  Return the error and discard the
buffer immediately on write attempt.

BO_DIRTY now always set during vnode reclamation, since it is used not
only for the INVARIANTS checks.  Do allow placement of the clean
buffers on dead bufobj list, otherwise filesystems cannot use bufcache
at all after the devvp reclaim.

Reported and tested by:	trasz
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2015-07-11 11:21:56 +00:00
parent f405d8eb61
commit cf88021ab1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=285384
2 changed files with 9 additions and 3 deletions

View File

@ -1205,6 +1205,12 @@ bufwrite(struct buf *bp)
int vp_md;
CTR3(KTR_BUF, "bufwrite(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags);
if ((bp->b_bufobj->bo_flag & BO_DEAD) != 0) {
bp->b_flags |= B_INVAL | B_RELBUF;
bp->b_flags &= ~B_CACHE;
brelse(bp);
return (ENXIO);
}
if (bp->b_flags & B_INVAL) {
brelse(bp);
return (0);

View File

@ -1584,7 +1584,8 @@ buf_vlist_add(struct buf *bp, struct bufobj *bo, b_xflags_t xflags)
int error;
ASSERT_BO_WLOCKED(bo);
KASSERT((bo->bo_flag & BO_DEAD) == 0, ("dead bo %p", bo));
KASSERT((xflags & BX_VNDIRTY) == 0 || (bo->bo_flag & BO_DEAD) == 0,
("dead bo %p", bo));
KASSERT((bp->b_xflags & (BX_VNDIRTY|BX_VNCLEAN)) == 0,
("buf_vlist_add: Buf %p has existing xflags %d", bp, bp->b_xflags));
bp->b_xflags |= xflags;
@ -2841,7 +2842,7 @@ vgonel(struct vnode *vp)
while (vinvalbuf(vp, 0, 0, 0) != 0)
;
}
#ifdef INVARIANTS
BO_LOCK(&vp->v_bufobj);
KASSERT(TAILQ_EMPTY(&vp->v_bufobj.bo_dirty.bv_hd) &&
vp->v_bufobj.bo_dirty.bv_cnt == 0 &&
@ -2850,7 +2851,6 @@ vgonel(struct vnode *vp)
("vp %p bufobj not invalidated", vp));
vp->v_bufobj.bo_flag |= BO_DEAD;
BO_UNLOCK(&vp->v_bufobj);
#endif
/*
* Reclaim the vnode.