Subject: Re: RFC: addition of B_MANAGED and B_NESTED to buf.h and vfs_bio.c
To: Reinoud Zandijk <reinoud@netbsd.org>
From: Greg Oster <oster@cs.usask.ca>
List: tech-kern
Date: 01/03/2006 14:43:39
Reinoud Zandijk writes:
>
> Index: kern/vfs_bio.c
> ===================================================================
> RCS file: /cvsroot/src/sys/kern/vfs_bio.c,v
> retrieving revision 1.148
> diff -u -r1.148 vfs_bio.c
> --- kern/vfs_bio.c 24 Dec 2005 19:12:23 -0000 1.148
> +++ kern/vfs_bio.c 3 Jan 2006 16:05:47 -0000
> @@ -904,6 +904,16 @@
> wakeup(bp);
> }
>
[snip]
>
> /*
> + * Get a new managed buffer. Memory assigned to it is NOT owned by the buffe
> r
> + * cache but by the caller, typically a filingsystem.
> + */
> +struct buf *
> +getmanagedbuf(int blkno, caddr_t base, int size)
> +{
> + int s;
> + struct buf *bp;
> +
> + KASSERT(base != NULL);
> + KASSERT(size > 0);
> +
> + s = splbio();
> + simple_lock(&bqueue_slock);
> +
> + /* please don't destroy valueable data */
> + bp = pool_get(&bufpool, PR_WAITOK);
> +
> + /* Initialise buffer */
> + memset(bp, 0, sizeof(struct buf));
> + BUF_INIT(bp);
> + bp->b_flags |= B_MANAGED;
> +
> + bp->b_blkno = blkno;
> + bp->b_data = base;
> + bp->b_bufsize = bp->b_bcount = bp->b_resid = size;
> +
> + simple_unlock(&bqueue_slock);
> + splx(s);
is locking/unlocking bqueue_slock really needed here? Isn't that
just for mucking with bufqueues[] and friends? Also, are you allowed
to PR_WAITOK w/ bqueue_slock locked?? (I don't think so...) If nothing
else, can the unlock and splx() be moved up to right after the
pool_get() ? (i.e. only block things for as long as really necessary? )
(sys/kern_physio.c:getphysbuf() seems to indicate that the
simple_lock/simple_unlock for pool_get(&bufpool,_) isn't needed.)
> +
> + return bp;
> +}
> +
> +/*
> + * Get a new buffer nested into the specified buffer at the given offset and
> + * length. NO read/write actions ought to be caried out on the master buffer
> + * anymore only on the nested buffers as they effectively split up the maste
> r
> + * buffer's action.
> + *
> + * Bug alert: make sure all nested buffers cover the complete mbp->resid
> + * space. If space is to be skipped, mbp->resid needs to be accounted for o
> r
> + * the biodone on mbp won't be called!
> + */
> +struct buf *
> +nestbuf(struct buf *mbp, int blkno, caddr_t base, int size)
> +{
> + int s;
> + struct buf *bp;
> +
> + KASSERT(base != NULL);
> + KASSERT(size > 0);
> + KASSERT((mpb==NULL) || (mpb && mbp->b_count < offset+size));
> +
> + s = splbio();
> + simple_lock(&bqueue_slock);
Again, is this needed?
> + /* please don't destroy valueable data */
> + bp = pool_get(&bufpool, PR_WAITOK);
Again, I don't think you can PR_WAITOK w/ a lock held. A LOCKDEBUG
kernel would have a fit :)
> + /*
> + * Adjust relevant information from the master buffer. set nested info
> + * and clear callback info and softdep info.
> + */
> + memcpy(bp, mbp, sizeof(struct buf));
> + bp->b_flags &= ~B_CALL;
> + bp->b_flags |= B_MANAGED | B_NESTED;
> + bp->b_masterbuf = mbp;
> +
> + bp->b_blkno = blkno;
> + bp->b_data = base;
> + bp->b_bufsize = bp->b_bcount = bp->b_resid = size;
> +
> + /* avoid confusion for softdep? */
> + LIST_INIT(&bp->b_dep);
Missing a:
simple_unlock(&bqueue_slock);
splx(s);
here? (or, preferably, right after the pool_get() if that would be
sufficient.
> + return bp;
> +}
Later...
Greg Oster