Move the buffer method vector (buf->b_op) to the bufobj.

Extend it with a strategy method.

Add bufstrategy() which do the usual VOP_SPECSTRATEGY/VOP_STRATEGY
song and dance.

Rename ibwrite to bufwrite().

Move the two NFS buf_ops to more sensible places, add bufstrategy
to them.

Add inlines for bwrite() and bstrategy() which calls through
buf->b_bufobj->b_ops->b_{write,strategy}().

Replace almost all VOP_STRATEGY()/VOP_SPECSTRATEGY() calls with bstrategy().
This commit is contained in:
Poul-Henning Kamp 2004-10-24 20:03:41 +00:00
parent 9d6c85734d
commit b792bebeea
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=136927
19 changed files with 113 additions and 104 deletions

View File

@ -193,7 +193,7 @@ ext2_bmaparray(vp, bn, bnp, runp, runb)
bp->b_ioflags &= ~BIO_ERROR;
vfs_busy_pages(bp, 0);
bp->b_iooffset = dbtob(bp->b_blkno);
VOP_STRATEGY(bp->b_vp, bp);
bstrategy(bp);
curproc->p_stats->p_ru.ru_inblock++; /* XXX */
error = bufwait(bp);
if (error) {

View File

@ -399,7 +399,7 @@ ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
bp->b_blkno = dbn;
vfs_busy_pages(bp, 0);
bp->b_iooffset = dbtob(bp->b_blkno);
VOP_STRATEGY(vp, bp);
bstrategy(bp);
error = bufwait(bp);
}
if (error) {

View File

@ -193,7 +193,7 @@ ext2_bmaparray(vp, bn, bnp, runp, runb)
bp->b_ioflags &= ~BIO_ERROR;
vfs_busy_pages(bp, 0);
bp->b_iooffset = dbtob(bp->b_blkno);
VOP_STRATEGY(bp->b_vp, bp);
bstrategy(bp);
curproc->p_stats->p_ru.ru_inblock++; /* XXX */
error = bufwait(bp);
if (error) {

View File

@ -399,7 +399,7 @@ ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
bp->b_blkno = dbn;
vfs_busy_pages(bp, 0);
bp->b_iooffset = dbtob(bp->b_blkno);
VOP_STRATEGY(vp, bp);
bstrategy(bp);
error = bufwait(bp);
}
if (error) {

View File

@ -61,12 +61,10 @@ static MALLOC_DEFINE(M_BIOBUF, "BIO buffer", "BIO buffer");
struct bio_ops bioops; /* I/O operation notification */
static int ibwrite(struct buf *);
static int inmem(struct vnode * vp, daddr_t blkno);
struct buf_ops buf_ops_bio = {
"buf_ops_bio",
ibwrite
.bop_name = "buf_ops_bio",
.bop_write = bufwrite,
.bop_strategy = bufstrategy,
};
/*
@ -77,6 +75,7 @@ struct buf *buf; /* buffer header pool */
static struct proc *bufdaemonproc;
static int inmem(struct vnode * vp, daddr_t blkno);
static void vm_hold_free_pages(struct buf *bp, vm_offset_t from,
vm_offset_t to);
static void vm_hold_load_pages(struct buf *bp, vm_offset_t from,
@ -724,10 +723,7 @@ breadn(struct vnode * vp, daddr_t blkno, int size,
bp->b_rcred = crhold(cred);
vfs_busy_pages(bp, 0);
bp->b_iooffset = dbtob(bp->b_blkno);
if (vp->v_type == VCHR)
VOP_SPECSTRATEGY(vp, bp);
else
VOP_STRATEGY(vp, bp);
bstrategy(bp);
++readwait;
}
@ -748,10 +744,7 @@ breadn(struct vnode * vp, daddr_t blkno, int size,
vfs_busy_pages(rabp, 0);
BUF_KERNPROC(rabp);
rabp->b_iooffset = dbtob(rabp->b_blkno);
if (vp->v_type == VCHR)
VOP_SPECSTRATEGY(vp, rabp);
else
VOP_STRATEGY(vp, rabp);
bstrategy(rabp);
} else {
brelse(rabp);
}
@ -775,16 +768,7 @@ breadn(struct vnode * vp, daddr_t blkno, int size,
* here.
*/
int
bwrite(struct buf *bp)
{
KASSERT(bp->b_op != NULL && bp->b_op->bop_write != NULL,
("Martian buffer %p in bwrite: nobody to write it.", bp));
return (bp->b_op->bop_write(bp));
}
static int
ibwrite(struct buf *bp)
bufwrite(struct buf *bp)
{
int oldflags, s;
struct buf *newbp;
@ -797,7 +781,7 @@ ibwrite(struct buf *bp)
oldflags = bp->b_flags;
if (BUF_REFCNT(bp) == 0)
panic("ibwrite: buffer is not busy???");
panic("bufwrite: buffer is not busy???");
s = splbio();
/*
* If a background write is already in progress, delay
@ -815,7 +799,7 @@ ibwrite(struct buf *bp)
bp->b_vflags |= BV_BKGRDWAIT;
msleep(&bp->b_xflags, BO_MTX(bp->b_bufobj), PRIBIO, "bwrbg", 0);
if (bp->b_vflags & BV_BKGRDINPROG)
panic("ibwrite: still writing");
panic("bufwrite: still writing");
}
BO_UNLOCK(bp->b_bufobj);
@ -895,12 +879,7 @@ ibwrite(struct buf *bp)
if (oldflags & B_ASYNC)
BUF_KERNPROC(bp);
bp->b_iooffset = dbtob(bp->b_blkno);
if (bp->b_vp->v_type == VCHR) {
if (!buf_prewrite(bp->b_vp, bp))
VOP_SPECSTRATEGY(bp->b_vp, bp);
} else {
VOP_STRATEGY(bp->b_vp, bp);
}
bstrategy(bp);
if ((oldflags & B_ASYNC) == 0) {
int rtval = bufwait(bp);
@ -1944,7 +1923,6 @@ getnewbuf(int slpflag, int slptimeo, int size, int maxsize)
bp->b_npages = 0;
bp->b_dirtyoff = bp->b_dirtyend = 0;
bp->b_magic = B_MAGIC_BIO;
bp->b_op = &buf_ops_bio;
bp->b_object = NULL;
bp->b_bufobj = NULL;
@ -3803,8 +3781,6 @@ bwait(struct buf *bp, u_char pri, const char *wchan)
mtx_unlock(&bdonelock);
}
#if 0 /* this is here to unconfuse p4 diff */
void
bufstrategy(struct bufobj *bo, struct buf *bp)
{
@ -3812,15 +3788,20 @@ bufstrategy(struct bufobj *bo, struct buf *bp)
struct vnode *vp;
vp = bp->b_vp;
#if 0
KASSERT(vp == bo->bo_vnode, ("Inconsistent vnode bufstrategy"));
KASSERT(vp->v_type != VCHR && vp->v_type != VBLK,
("Wrong vnode in bufstrategy(bp=%p, vp=%p)", bp, vp));
i = VOP_STRATEGY(vp, bp);
#endif
if (vp->v_type == VCHR) {
if (!buf_prewrite(bp->b_vp, bp))
i = VOP_SPECSTRATEGY(vp, bp);
} else {
i = VOP_STRATEGY(vp, bp);
}
KASSERT(i == 0, ("VOP_STRATEGY failed bp=%p vp=%p", bp, bp->b_vp));
}
#endif
void
bufobj_wref(struct bufobj *bo)
{

View File

@ -236,10 +236,8 @@ cluster_read(vp, filesize, lblkno, size, cred, totread, seqcount, bpp)
if ((bp->b_flags & B_ASYNC) || bp->b_iodone != NULL)
BUF_KERNPROC(bp);
bp->b_iooffset = dbtob(bp->b_blkno);
error = VOP_STRATEGY(vp, bp);
bstrategy(bp);
curproc->p_stats->p_ru.ru_inblock++;
if (error)
return (error);
}
/*
@ -291,7 +289,7 @@ cluster_read(vp, filesize, lblkno, size, cred, totread, seqcount, bpp)
if ((rbp->b_flags & B_ASYNC) || rbp->b_iodone != NULL)
BUF_KERNPROC(rbp);
rbp->b_iooffset = dbtob(rbp->b_blkno);
(void) VOP_STRATEGY(vp, rbp);
bstrategy(rbp);
curproc->p_stats->p_ru.ru_inblock++;
}
@ -824,7 +822,6 @@ cluster_wbuild(vp, size, start_lbn, len)
TAILQ_INIT(&bp->b_cluster.cluster_head);
bp->b_bcount = 0;
bp->b_magic = tbp->b_magic;
bp->b_op = tbp->b_op;
bp->b_bufobj = tbp->b_bufobj;
bp->b_bufsize = 0;
bp->b_npages = 0;

View File

@ -841,6 +841,7 @@ getnewvnode(tag, mp, vops, vpp)
TAILQ_INIT(&bo->bo_clean.bv_hd);
TAILQ_INIT(&bo->bo_dirty.bv_hd);
bo->bo_ops = &buf_ops_bio;
vp->v_type = VNON;
vp->v_tag = tag;
vp->v_op = vops;

View File

@ -2956,7 +2956,7 @@ nfs4_writebp(struct buf *bp, int force __unused, struct thread *td)
BUF_KERNPROC(bp);
bp->b_iooffset = dbtob(bp->b_blkno);
VOP_STRATEGY(bp->b_vp, bp);
bstrategy(bp);
if( (oldflags & B_ASYNC) == 0) {
int rtval = bufwait(bp);
@ -3081,3 +3081,22 @@ nfsfifo_close(struct vop_close_args *ap)
}
#endif
/*
* Just call nfs_writebp() with the force argument set to 1.
*
* NOTE: B_DONE may or may not be set in a_bp on call.
*/
static int
nfs4_bwrite(struct buf *bp)
{
return (nfs4_writebp(bp, 1, curthread));
}
struct buf_ops buf_ops_nfs4 = {
.bop_name = "buf_ops_nfs4",
.bop_write = nfs4_bwrite,
.bop_strategy = bufstrategy,
};

View File

@ -64,35 +64,6 @@ __FBSDID("$FreeBSD$");
#include <nfs4client/nfs4.h>
/*
* Just call nfs_writebp() with the force argument set to 1.
*
* NOTE: B_DONE may or may not be set in a_bp on call.
*/
static int
nfs4_bwrite(struct buf *bp)
{
return (nfs4_writebp(bp, 1, curthread));
}
static int
nfs_bwrite(struct buf *bp)
{
return (nfs_writebp(bp, 1, curthread));
}
struct buf_ops buf_ops_nfs4 = {
"buf_ops_nfs4",
nfs4_bwrite
};
struct buf_ops buf_ops_nfs = {
"buf_ops_nfs",
nfs_bwrite
};
static struct buf *nfs_getcacheblk(struct vnode *vp, daddr_t bn, int size,
struct thread *td);
@ -866,10 +837,6 @@ nfs_write(struct vop_write_args *ap)
allocbuf(bp, bcount);
bp->b_flags |= save;
bp->b_magic = B_MAGIC_NFS;
if ((nmp->nm_flag & NFSMNT_NFSV4) != 0)
bp->b_op = &buf_ops_nfs4;
else
bp->b_op = &buf_ops_nfs;
}
} else {
/*
@ -1403,7 +1370,7 @@ nfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td)
off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
retv = (nmp->nm_rpcops->nr_commit)(
bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff,
vp, off, bp->b_dirtyend-bp->b_dirtyoff,
bp->b_wcred, td);
if (retv == 0) {
bp->b_dirtyoff = bp->b_dirtyend = 0;
@ -1413,7 +1380,7 @@ nfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td)
return (0);
}
if (retv == NFSERR_STALEWRITEVERF) {
nfs_clearcommit(bp->b_vp->v_mount);
nfs_clearcommit(vp->v_mount);
}
}

View File

@ -247,6 +247,10 @@ nfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp)
return (error);
}
vp = nvp;
if (nmp->nm_flag & NFSMNT_NFSV4)
vp->v_bufobj.bo_ops = &buf_ops_nfs4;
else
vp->v_bufobj.bo_ops = &buf_ops_nfs;
bzero((caddr_t)np, sizeof *np);
vp->v_data = np;
np->n_vnode = vp;

View File

@ -2930,7 +2930,7 @@ nfs_writebp(struct buf *bp, int force __unused, struct thread *td)
BUF_KERNPROC(bp);
bp->b_iooffset = dbtob(bp->b_blkno);
VOP_STRATEGY(bp->b_vp, bp);
bstrategy(bp);
if( (oldflags & B_ASYNC) == 0) {
int rtval = bufwait(bp);
@ -3053,3 +3053,20 @@ nfsfifo_close(struct vop_close_args *ap)
return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
}
/*
* Just call nfs_writebp() with the force argument set to 1.
*
* NOTE: B_DONE may or may not be set in a_bp on call.
*/
static int
nfs_bwrite(struct buf *bp)
{
return (nfs_writebp(bp, 1, curthread));
}
struct buf_ops buf_ops_nfs = {
.bop_name = "buf_ops_nfs",
.bop_write = nfs_bwrite,
.bop_strategy = bufstrategy,
};

View File

@ -193,11 +193,13 @@ nfs_rsunlock(struct nfsnode *np, struct thread *td)
extern vop_t **fifo_nfsnodeop_p;
extern vop_t **nfs_vnodeop_p;
extern struct buf_ops buf_ops_nfs;
#if 0
extern vop_t **fifo_nfs4nodeop_p;
#endif
extern vop_t **nfs4_vnodeop_p;
extern struct buf_ops buf_ops_nfs4;
/*
* Prototypes for NFS vnode operations

View File

@ -38,6 +38,7 @@
#ifndef _SYS_BUF_H_
#define _SYS_BUF_H_
#include <sys/bufobj.h>
#include <sys/queue.h>
#include <sys/lock.h>
#include <sys/lockmgr.h>
@ -67,13 +68,6 @@ extern struct bio_ops {
int (*io_countdeps)(struct buf *, int);
} bioops;
struct buf_ops {
char *bop_name;
int (*bop_write)(struct buf *);
};
extern struct buf_ops buf_ops_bio;
struct vm_object;
typedef unsigned char b_xflags_t;
@ -110,7 +104,6 @@ struct buf {
#define b_ioflags b_io.bio_flags
#define b_iooffset b_io.bio_offset
#define b_resid b_io.bio_resid
struct buf_ops *b_op;
struct bufobj *b_bufobj;
unsigned b_magic;
#define B_MAGIC_BIO 0x10b10b10
@ -402,6 +395,25 @@ struct cluster_save {
#ifdef _KERNEL
static __inline int
bwrite(struct buf *bp)
{
KASSERT(bp->b_bufobj != NULL, ("bwrite: no bufobj bp=%p", bp));
KASSERT(bp->b_bufobj->bo_ops != NULL, ("bwrite: no bo_ops bp=%p", bp));
KASSERT(bp->b_bufobj->bo_ops->bop_write != NULL,
("bwrite: no bop_write bp=%p", bp));
return (bp->b_bufobj->bo_ops->bop_write(bp));
}
static __inline void
bstrategy(struct buf *bp)
{
KASSERT(bp->b_bufobj != NULL, ("bwrite: no bufobj bp=%p", bp));
KASSERT(bp->b_bufobj->bo_ops != NULL, ("bwrite: no bo_ops bp=%p", bp));
KASSERT(bp->b_bufobj->bo_ops->bop_strategy != NULL,
("bwrite: no bop_strategy bp=%p", bp));
bp->b_bufobj->bo_ops->bop_strategy(bp->b_bufobj, bp);
}
static __inline int
buf_prewrite(struct vnode *vp, struct buf *bp)
@ -488,11 +500,11 @@ void bremfree(struct buf *);
int bread(struct vnode *, daddr_t, int, struct ucred *, struct buf **);
int breadn(struct vnode *, daddr_t, int, daddr_t *, int *, int,
struct ucred *, struct buf **);
int bwrite(struct buf *);
void bdwrite(struct buf *);
void bawrite(struct buf *);
void bdirty(struct buf *);
void bundirty(struct buf *);
void bufstrategy(struct bufobj *, struct buf *);
void brelse(struct buf *);
void bqrelse(struct buf *);
int vfs_bio_awrite(struct buf *);
@ -502,6 +514,7 @@ struct buf *gbincore(struct bufobj *, daddr_t);
struct buf *getblk(struct vnode *, daddr_t, int, int, int, int);
struct buf *geteblk(int);
int bufwait(struct buf *);
int bufwrite(struct buf *);
void bufdone(struct buf *);
void cluster_callback(struct buf *);

View File

@ -53,6 +53,11 @@
#include <sys/queue.h>
struct bufobj;
struct buf_ops;
extern struct buf_ops buf_ops_bio;
TAILQ_HEAD(buflists, buf);
/* A Buffer splay list */
@ -62,12 +67,22 @@ struct bufv {
int bv_cnt; /* Number of buffers */
};
typedef void b_strategy_t(struct bufobj *, struct buf *);
typedef int b_write_t(struct buf *);
struct buf_ops {
char *bop_name;
b_write_t *bop_write;
b_strategy_t *bop_strategy;
};
struct bufobj {
struct mtx *bo_mtx; /* Mutex which protects "i" things */
struct bufv bo_clean; /* i Clean buffers */
struct bufv bo_dirty; /* i Dirty buffers */
long bo_numoutput; /* i Writes in progress */
u_int bo_flag; /* i Flags */
struct buf_ops *bo_ops; /* - buffer operatoins */
};
#define BO_WWAIT (1 << 1) /* Wait for output to complete */

View File

@ -562,7 +562,7 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
bp->b_blkno = dbn;
vfs_busy_pages(bp, 0);
bp->b_iooffset = dbtob(bp->b_blkno);
VOP_STRATEGY(bp->b_vp, bp);
bstrategy(bp);
error = bufwait(bp);
}
if (error) {

View File

@ -225,7 +225,7 @@ ufs_bmaparray(vp, bn, bnp, nbp, runp, runb)
bp->b_ioflags &= ~BIO_ERROR;
vfs_busy_pages(bp, 0);
bp->b_iooffset = dbtob(bp->b_blkno);
VOP_STRATEGY(bp->b_vp, bp);
bstrategy(bp);
curproc->p_stats->p_ru.ru_inblock++; /* XXX */
error = bufwait(bp);
if (error) {

View File

@ -2551,7 +2551,7 @@ swapdev_strategy(struct buf *bp, struct swdevt *sp)
bp->b_vp = vp2;
splx(s);
bp->b_iooffset = dbtob(bp->b_blkno);
VOP_STRATEGY(vp2, bp);
bstrategy(bp);
return;
}

View File

@ -296,7 +296,6 @@ initpbuf(struct buf *bp)
bp->b_iodone = NULL;
bp->b_error = 0;
bp->b_magic = B_MAGIC_BIO;
bp->b_op = &buf_ops_bio;
BUF_LOCK(bp, LK_EXCLUSIVE, NULL);
}

View File

@ -479,10 +479,7 @@ vnode_pager_input_smlfs(object, m)
/* do the input */
bp->b_iooffset = dbtob(bp->b_blkno);
if (dp->v_type == VCHR)
VOP_SPECSTRATEGY(bp->b_vp, bp);
else
VOP_STRATEGY(bp->b_vp, bp);
bstrategy(bp);
/* we definitely need to be at splvm here */
@ -833,10 +830,7 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
/* do the input */
bp->b_iooffset = dbtob(bp->b_blkno);
if (dp->v_type == VCHR)
VOP_SPECSTRATEGY(bp->b_vp, bp);
else
VOP_STRATEGY(bp->b_vp, bp);
bstrategy(bp);
bwait(bp, PVM, "vnread");