Subject: Re: brelse() nonsense
To: Pedro Martelletto <pedro@ambientworks.net>
From: Rui Paulo <rpaulo@NetBSD.org>
List: tech-kern
Date: 07/24/2005 19:01:12
Hi Pedro, sorry for the late reply!
On Mon, Jun 13, 2005 at 03:26:54PM -0300, Pedro Martelletto wrote:
> Hi,
>
> Currently, in brelse(), when disassociating a buffer from a vnode,
> the B_DELWRI flag is first removed, then reassignbuf() is called
> followed by brelvp().
>
> reassignbuf() first removes the buffer from the vnode's clean or dirty
> list, then checks for the B_DELWRI flag, which is absent, and inserts
> the buffer in the vnode's clean list. It also checks if the vnode is on
> the sync list with no dirty buffers, in which case it is removed.
>
> When brelvp() is called, the buffer is removed from the vnode's clean
> list, and the 'on sync list with no dirty buffers' check is performed
> again.
>
> I don't think the call to reassignbuf() is necessary, and since it's in
> code protected by IPL_BIO, it might be slowing things down a bit.
-vfs_bio.c-
void
brelse(struct buf *bp)
{
...
if ((bp->b_bufsize <= 0) || ISSET(bp->b_flags, B_INVAL)) {
/*
* If it's invalid or empty, dissociate it from its vnode
* and put on the head of the appropriate queue.
*/
if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_deallocate)
(*bioops.io_deallocate)(bp);
CLR(bp->b_flags, B_DONE|B_DELWRI);
if (bp->b_vp) {
reassignbuf(bp, bp->b_vp);
brelvp(bp);
}
...
}
...
}
-vfs_subr.c-
void
reassignbuf(struct buf *bp, struct vnode *newvp)
{
...
if ((bp->b_flags & B_DELWRI) == 0) {
listheadp = &newvp->v_cleanblkhd;
if (TAILQ_EMPTY(&newvp->v_uobj.memq) &&
(newvp->v_flag & VONWORKLST) &&
LIST_FIRST(&newvp->v_dirtyblkhd) == NULL) {
newvp->v_flag &= ~(VWRITEMAPDIRTY|VONWORKLST);
LIST_REMOVE(newvp, v_synclist);
}
...
}
...
bufinsvn(bp, listheadp);
}
void
brelvp(struct buf *bp)
{
...
vp = bp->b_vp;
...
if (TAILQ_EMPTY(&vp->v_uobj.memq) && (vp->v_flag & VONWORKLST) &&
LIST_FIRST(&vp->v_dirtyblkhd) == NULL) {
vp->v_flag &= ~(VWRITEMAPDIRTY|VONWORKLST);
LIST_REMOVE(vp, v_synclist);
}
...
}
So, the vnode is never on the clean list. Also, bufinsvn() is just inserting
the buffer in the same list again, if I understand it correctly.
I didn't tested your change, but it makes sense to me.
-- Rui Paulo