Subject: Make VOP_STRATEGY a real VOP
To: None <tech-kern@netbsd.org>
From: Juergen Hannken-Illjes <hannken@eis.cs.tu-bs.de>
List: tech-kern
Date: 01/19/2004 20:04:20
--gBBFr7Ir9EOA20Yy
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

VOP_STRATEGY is no real VOP because it is missing a vnode as a first
argument. I propose to convert  VOP_STRATEGY(bp)  to two functions
VOP_STRATEGY(vp, bp)  and  DEV_STRATEGY(bp)  as follows:

 VOP_STRATEGY(vp, bp) will run the strategy routine for the  vp  arg
 and the conversion is like  VOP_STRATEGY(bp) -> VOP_STRATEGY(bp->b_vp, bp).

 DEV_STRATEGY(bp) is used for block-to-block device situations and calls
 the d_strategy() routine from device bp->b_dev.
 
With these changes applied, VOP_STRATEGY is no longer a special-case VOP
and spec_strategy() always gets the vnode of the block device to call.
This will make it more easy to put copy-on-write data into the specinfo
of the block device.

Comments?
-- 
Juergen Hannken-Illjes - hannken@eis.cs.tu-bs.de - TU Braunschweig (Germany)

--gBBFr7Ir9EOA20Yy
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="vop.diff"

Index: dev/ccd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ccd.c,v
retrieving revision 1.94
diff -u -1 -0 -r1.94 ccd.c
--- dev/ccd.c	10 Jan 2004 14:39:50 -0000	1.94
+++ dev/ccd.c	19 Jan 2004 18:53:32 -0000
@@ -765,21 +765,21 @@
 		}
 
 		/* Transfer all set up, remove job from the queue. */
 		(void) BUFQ_GET(&cs->sc_bufq);
 
 		/* Now fire off the requests. */
 		while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) {
 			SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q);
 			if ((cbp->cb_buf.b_flags & B_READ) == 0)
 				cbp->cb_buf.b_vp->v_numoutput++;
-			VOP_STRATEGY(&cbp->cb_buf);
+			DEV_STRATEGY(&cbp->cb_buf);
 		}
 	}
 }
 
 /*
  * Build a component buffer header.
  */
 static struct ccdbuf *
 ccdbuffer(cs, bp, bn, addr, bcount)
 	struct ccd_softc *cs;
Index: dev/cgd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/cgd.c,v
retrieving revision 1.13
diff -u -1 -0 -r1.13 cgd.c
--- dev/cgd.c	10 Jan 2004 14:39:50 -0000	1.13
+++ dev/cgd.c	19 Jan 2004 18:53:32 -0000
@@ -317,21 +317,21 @@
 	cbp->cb_buf.b_bcount = bp->b_bcount;
 
 	/* context for cgdiodone */
 	cbp->cb_obp = bp;
 	cbp->cb_sc = cs;
 
 	BIO_COPYPRIO(&cbp->cb_buf, bp);
 
 	if ((cbp->cb_buf.b_flags & B_READ) == 0)
 		cbp->cb_buf.b_vp->v_numoutput++;
-	VOP_STRATEGY(&cbp->cb_buf);
+	VOP_STRATEGY(cs->sc_tvn, &cbp->cb_buf);
 }
 
 void
 cgdiodone(struct buf *vbp)
 {
 	struct	cgdbuf *cbp = (struct cgdbuf *)vbp;
 	struct	buf *obp = cbp->cb_obp;
 	struct	buf *nbp = &cbp->cb_buf;
 	struct	cgd_softc *cs = cbp->cb_sc;
 	struct	dk_softc *dksc = &cs->sc_dksc;
Index: dev/fss.c
===================================================================
RCS file: /cvsroot/src/sys/dev/fss.c,v
retrieving revision 1.4
diff -u -1 -0 -r1.4 fss.c
--- dev/fss.c	11 Jan 2004 19:05:27 -0000	1.4
+++ dev/fss.c	19 Jan 2004 18:53:33 -0000
@@ -995,21 +995,21 @@
 		bp->b_data = addr;
 		bp->b_blkno = bp->b_rawblkno = nbn+btodb(FSS_FSBOFF(sc, pos));
 		bp->b_proc = NULL;
 		bp->b_vp = NULLVP;
 		bp->b_private = scp;
 		bp->b_iodone = fss_cluster_iodone;
 		bgetvp(vp, bp);
 		bp->b_vp->v_numoutput++;
 
 		BIO_SETPRIO(bp, BPRIO_TIMECRITICAL);
-		VOP_STRATEGY(bp);
+		VOP_STRATEGY(vp, bp);
 
 		FSS_LOCK(sc, s);
 		scp->fc_xfercount++;
 		FSS_UNLOCK(sc, s);
 
 		pos += len;
 		addr += len;
 		todo -= len;
 	}
 
@@ -1062,21 +1062,21 @@
 		bp->b_data = data;
 		bp->b_blkno = bp->b_rawblkno = nbn+btodb(FSS_FSBOFF(sc, pos));
 		bp->b_proc = NULL;
 		bp->b_vp = NULLVP;
 		bgetvp(vp, bp);
 		if ((bp->b_flags & B_READ) == 0)
 			bp->b_vp->v_numoutput++;
 
 		if ((bp->b_flags & B_READ) == 0 || cl < sc->sc_indir_size)
 			BIO_SETPRIO(bp, BPRIO_TIMECRITICAL);
-		VOP_STRATEGY(bp);
+		VOP_STRATEGY(vp, bp);
 
 		error = biowait(bp);
 
 		if (bp->b_vp != NULL)
 			brelvp(bp);
 
 		s = splbio();
 		pool_put(&bufpool, bp);
 		splx(s);
 
Index: dev/vnd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/vnd.c,v
retrieving revision 1.105
diff -u -1 -0 -r1.105 vnd.c
--- dev/vnd.c	10 Jan 2004 14:39:50 -0000	1.105
+++ dev/vnd.c	19 Jan 2004 18:53:36 -0000
@@ -636,21 +636,21 @@
 				" flags %lx addr %p cnt 0x%lx\n",
 			    (long) (vnd-vnd_softc), bp, bp->b_vp, bp->b_blkno,
 			    bp->b_flags, bp->b_data, bp->b_bcount);
 #endif
 
 		/* Instrumentation. */
 		disk_busy(&vnd->sc_dkdev);
 
 		if ((bp->b_flags & B_READ) == 0)
 			bp->b_vp->v_numoutput++;
-		VOP_STRATEGY(bp);
+		VOP_STRATEGY(bp->b_vp, bp);
 	}
 	vnd->sc_flags &= ~VNF_BUSY;
 }
 
 void
 vndiodone(bp)
 	struct buf *bp;
 {
 	struct vndbuf *vbp = (struct vndbuf *) bp;
 	struct vndxfer *vnx = (struct vndxfer *)vbp->vb_xfer;
Index: dev/ata/ata_raid.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/ata_raid.c,v
retrieving revision 1.7
diff -u -1 -0 -r1.7 ata_raid.c
--- dev/ata/ata_raid.c	14 Dec 2003 05:37:25 -0000	1.7
+++ dev/ata/ata_raid.c	19 Jan 2004 18:53:38 -0000
@@ -302,18 +302,18 @@
 	BUF_INIT(bp);
 
 	bp->b_vp = vp;
 	bp->b_dev = vp->v_rdev;
 	bp->b_blkno = blkno;
 	bp->b_bcount = bp->b_resid = size;
 	bp->b_flags = bflags;
 	bp->b_proc = curproc;
 	bp->b_data = buf;
 
-	VOP_STRATEGY(bp);
+	VOP_STRATEGY(vp, bp);
 	error = biowait(bp);
 
 	s = splbio();
 	pool_put(&bufpool, bp);
 	splx(s);
 	return (error);
 }
Index: dev/ata/ld_ataraid.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/ld_ataraid.c,v
retrieving revision 1.9
diff -u -1 -0 -r1.9 ld_ataraid.c
--- dev/ata/ld_ataraid.c	14 Dec 2003 02:46:34 -0000	1.9
+++ dev/ata/ld_ataraid.c	19 Jan 2004 18:53:39 -0000
@@ -304,21 +304,21 @@
 
 		SIMPLEQ_INSERT_TAIL(&cbufq, cbp, cb_q);
 		addr += rcount;
 	}
 
 	/* Now fire off the requests. */
 	while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) {
 		SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q);
 		if ((cbp->cb_buf.b_flags & B_READ) == 0)
 			cbp->cb_buf.b_vp->v_numoutput++;
-		VOP_STRATEGY(&cbp->cb_buf);
+		VOP_STRATEGY(cbp->cb_buf.b_vp, &cbp->cb_buf);
 	}
 
 	return (0);
 }
 
 static int
 ld_ataraid_start_raid0(struct ld_softc *ld, struct buf *bp)
 {
 	struct ld_ataraid_softc *sc = (void *) ld;
 	struct ataraid_array_info *aai = sc->sc_aai;
@@ -369,21 +369,21 @@
 		SIMPLEQ_INSERT_TAIL(&cbufq, cbp, cb_q);
 		bn += btodb(rcount);
 		addr += rcount;
 	}
 
 	/* Now fire off the requests. */
 	while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) {
 		SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q);
 		if ((cbp->cb_buf.b_flags & B_READ) == 0)
 			cbp->cb_buf.b_vp->v_numoutput++;
-		VOP_STRATEGY(&cbp->cb_buf);
+		VOP_STRATEGY(cbp->cb_buf.b_vp, &cbp->cb_buf);
 	}
 
 	return (0);
 }
 
 /*
  * Called at interrupt time.  Mark the component as done and if all
  * components are done, take an "interrupt".
  */
 static void
Index: dev/raidframe/rf_netbsdkintf.c
===================================================================
RCS file: /cvsroot/src/sys/dev/raidframe/rf_netbsdkintf.c,v
retrieving revision 1.172
diff -u -1 -0 -r1.172 rf_netbsdkintf.c
--- dev/raidframe/rf_netbsdkintf.c	10 Jan 2004 14:39:50 -0000	1.172
+++ dev/raidframe/rf_netbsdkintf.c	19 Jan 2004 18:53:43 -0000
@@ -1871,21 +1871,21 @@
 			    req->type, queue->raidPtr->raidid, 
 			    queue->col));
 		db1_printf(("sector %d count %d (%d bytes) %d\n",
 			(int) req->sectorOffset, (int) req->numSector,
 			(int) (req->numSector <<
 			    queue->raidPtr->logBytesPerSector),
 			(int) queue->raidPtr->logBytesPerSector));
 		if ((raidbp->rf_buf.b_flags & B_READ) == 0) {
 			raidbp->rf_buf.b_vp->v_numoutput++;
 		}
-		VOP_STRATEGY(&raidbp->rf_buf);
+		DEV_STRATEGY(&raidbp->rf_buf);
 
 		break;
 
 	default:
 		panic("bad req->type in rf_DispatchKernelIO");
 	}
 	db1_printf(("Exiting from DispatchKernelIO\n"));
 
 	return (0);
 }
Index: fs/adosfs/advnops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/adosfs/advnops.c,v
retrieving revision 1.6
diff -u -1 -0 -r1.6 advnops.c
--- fs/adosfs/advnops.c	29 Jun 2003 22:31:07 -0000	1.6
+++ fs/adosfs/advnops.c	19 Jan 2004 18:53:46 -0000
@@ -384,21 +384,20 @@
 		struct buf *a_bp;
 	} */ *sp = v;
 	struct buf *bp;
 	struct anode *ap;
 	struct vnode *vp;
 	int error;
 
 #ifdef ADOSFS_DIAGNOSTIC
 	advopprint(sp);
 #endif
-	error = 0;
 	bp = sp->a_bp;
 	if (bp->b_vp == NULL) {
 		bp->b_flags |= B_ERROR;
 		biodone(bp);
 		error = EIO;
 		goto reterr;
 	}
 	vp = bp->b_vp;
 	ap = VTOA(vp);
 	if (bp->b_blkno == bp->b_lblkno) {
@@ -409,21 +408,21 @@
 			goto reterr;
 		}
 	}
 	if ((long)bp->b_blkno == -1) {
 		biodone(bp);
 		error = 0;
 		goto reterr;
 	}
 	vp = ap->amp->devvp;
 	bp->b_dev = vp->v_rdev;
-	VOCALL(vp->v_op, VOFFSET(vop_strategy), sp);
+	error = VOP_STRATEGY(vp, bp);
 reterr:
 #ifdef ADOSFS_DIAGNOSTIC
 	printf(" %d)", error);
 #endif
 	return(error);
 }
 
 int
 adosfs_link(v) 
 	void *v;
Index: fs/cd9660/cd9660_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/cd9660/cd9660_vnops.c,v
retrieving revision 1.6
diff -u -1 -0 -r1.6 cd9660_vnops.c
--- fs/cd9660/cd9660_vnops.c	7 Aug 2003 16:31:36 -0000	1.6
+++ fs/cd9660/cd9660_vnops.c	19 Jan 2004 18:53:47 -0000
@@ -765,22 +765,21 @@
 		}
 		if ((long)bp->b_blkno == -1)
 			clrbuf(bp);
 	}
 	if ((long)bp->b_blkno == -1) {
 		biodone(bp);
 		return (0);
 	}
 	vp = ip->i_devvp;
 	bp->b_dev = vp->v_rdev;
-	VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
-	return (0);
+	return (VOP_STRATEGY(vp, bp));
 }
 
 /*
  * Print out the contents of an inode.
  */
 /*ARGSUSED*/
 int
 cd9660_print(v)
 	void *v;
 {
Index: fs/filecorefs/filecore_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/filecorefs/filecore_vnops.c,v
retrieving revision 1.6
diff -u -1 -0 -r1.6 filecore_vnops.c
--- fs/filecorefs/filecore_vnops.c	7 Aug 2003 16:31:38 -0000	1.6
+++ fs/filecorefs/filecore_vnops.c	19 Jan 2004 18:53:49 -0000
@@ -460,22 +460,21 @@
 		}
 		if ((long)bp->b_blkno == -1)
 			clrbuf(bp);
 	}
 	if ((long)bp->b_blkno == -1) {
 		biodone(bp);
 		return (0);
 	}
 	vp = ip->i_devvp;
 	bp->b_dev = vp->v_rdev;
-	VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
-	return (0);
+	return (VOP_STRATEGY(vp, bp));
 }
 
 /*
  * Print out the contents of an inode.
  */
 /*ARGSUSED*/
 int
 filecore_print(v)
 	void *v;
 {
Index: fs/msdosfs/msdosfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/msdosfs_vnops.c,v
retrieving revision 1.7
diff -u -1 -0 -r1.7 msdosfs_vnops.c
--- fs/msdosfs/msdosfs_vnops.c	7 Sep 2003 22:09:11 -0000	1.7
+++ fs/msdosfs/msdosfs_vnops.c	19 Jan 2004 18:53:52 -0000
@@ -1764,22 +1764,21 @@
 		return (error);
 	}
 
 	/*
 	 * Read/write the block from/to the disk that contains the desired
 	 * file block.
 	 */
 
 	vp = dep->de_devvp;
 	bp->b_dev = vp->v_rdev;
-	VOCALL(vp->v_op, VOFFSET(vop_strategy), ap);
-	return (0);
+	return (VOP_STRATEGY(vp, bp));
 }
 
 int
 msdosfs_print(v)
 	void *v;
 {
 	struct vop_print_args /* {
 		struct vnode *vp;
 	} */ *ap = v;
 	struct denode *dep = VTODE(ap->a_vp);
Index: fs/union/union_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/union/union_vnops.c,v
retrieving revision 1.7
diff -u -1 -0 -r1.7 union_vnops.c
--- fs/union/union_vnops.c	7 Aug 2003 16:31:40 -0000	1.7
+++ fs/union/union_vnops.c	19 Jan 2004 18:53:54 -0000
@@ -1979,41 +1979,35 @@
 /*
  * XXX - vop_strategy must be hand coded because it has no
  * vnode in its arguments.
  * This goes away with a merged VM/buffer cache.
  */
 int
 union_strategy(v)
 	void *v;
 {
 	struct vop_strategy_args /* {
+		struct vnode *a_vp;
 		struct buf *a_bp;
 	} */ *ap = v;
+	struct vnode *ovp = OTHERVP(ap->a_vp);
 	struct buf *bp = ap->a_bp;
-	int error;
-	struct vnode *savedvp;
-
-	savedvp = bp->b_vp;
-	bp->b_vp = OTHERVP(bp->b_vp);
 
 #ifdef DIAGNOSTIC
-	if (bp->b_vp == NULLVP)
+	if (ovp == NULLVP)
 		panic("union_strategy: nil vp");
 	if (((bp->b_flags & B_READ) == 0) &&
-	    (bp->b_vp == LOWERVP(savedvp)))
+	    (ovp == LOWERVP(bp->b_vp)))
 		panic("union_strategy: writing to lowervp");
 #endif
 
-	error = VOP_STRATEGY(bp);
-	bp->b_vp = savedvp;
-
-	return (error);
+	return (VOP_STRATEGY(ovp, bp));
 }
 
 int
 union_getpages(v)
 	void *v;
 {
 	struct vop_getpages_args /* {
 		struct vnode *a_vp;
 		voff_t a_offset;
 		struct vm_page **a_m;
Index: kern/vfs_bio.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_bio.c,v
retrieving revision 1.110
diff -u -1 -0 -r1.110 vfs_bio.c
--- kern/vfs_bio.c	15 Jan 2004 09:03:26 -0000	1.110
+++ kern/vfs_bio.c	19 Jan 2004 18:53:56 -0000
@@ -499,21 +499,21 @@
 	 * Note that if buffer is B_INVAL, getblk() won't return it.
 	 * Therefore, it's valid if its I/O has completed or been delayed.
 	 */
 	if (!ISSET(bp->b_flags, (B_DONE | B_DELWRI))) {
 		/* Start I/O for the buffer. */
 		SET(bp->b_flags, B_READ | async);
 		if (async)
 			BIO_SETPRIO(bp, BPRIO_TIMELIMITED);
 		else
 			BIO_SETPRIO(bp, BPRIO_TIMECRITICAL);
-		VOP_STRATEGY(bp);
+		VOP_STRATEGY(vp, bp);
 
 		/* Pay for the read. */
 		p->p_stats->p_ru.ru_inblock++;
 	} else if (async) {
 		brelse(bp);
 	}
 
 	return (bp);
 }
 
@@ -644,21 +644,21 @@
 	/* Initiate disk write.  Make sure the appropriate party is charged. */
 	V_INCR_NUMOUTPUT(bp->b_vp);
 	simple_unlock(&bp->b_interlock);
 	splx(s);
 
 	if (sync)
 		BIO_SETPRIO(bp, BPRIO_TIMECRITICAL);
 	else
 		BIO_SETPRIO(bp, BPRIO_TIMELIMITED);
 
-	VOP_STRATEGY(bp);
+	VOP_STRATEGY(vp, bp);
 
 	if (sync) {
 		/* If I/O was synchronous, wait for it to complete. */
 		rv = biowait(bp);
 
 		/* Release the buffer. */
 		brelse(bp);
 
 		return (rv);
 	} else {
Index: kern/vnode_if.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vnode_if.c,v
retrieving revision 1.45
diff -u -1 -0 -r1.45 vnode_if.c
--- kern/vnode_if.c	7 Aug 2003 16:32:05 -0000	1.45
+++ kern/vnode_if.c	19 Jan 2004 18:53:57 -0000
@@ -1,20 +1,20 @@
-/*	$NetBSD: vnode_if.c,v 1.45 2003/08/07 16:32:05 agc Exp $	*/
+/*	$NetBSD$	*/
 
 /*
  * Warning: This file is generated automatically.
  * (Modifications made here may easily be lost!)
  *
  * Created from the file:
- *	NetBSD: vnode_if.src,v 1.33 2003/04/10 20:35:36 jdolecek Exp 
+ *	NetBSD: vnode_if.src,v 1.36 2003/11/17 11:16:10 wiz Exp 
  * by the script:
- *	NetBSD: vnode_if.sh,v 1.30 2001/11/12 14:34:24 lukem Exp 
+ *	NetBSD: vnode_if.sh,v 1.33 2003/08/07 16:32:05 agc Exp 
  */
 
 /*
  * Copyright (c) 1992, 1993, 1994, 1995
  *	The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
@@ -33,21 +33,21 @@
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vnode_if.c,v 1.45 2003/08/07 16:32:05 agc Exp $");
+__KERNEL_RCSID(0, "$NetBSD$");
 
 
 /*
  * If we have LKM support, always include the non-inline versions for
  * LKMs.  Otherwise, do it based on the option.
  */
 #ifdef LKM
 #define	VNODE_OP_NOINLINE
 #else
 #include "opt_vnode_op_noinline.h"
@@ -66,51 +66,25 @@
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	NULL,
 };
 
 
 /* Special cases: */
 
-const int vop_strategy_vp_offsets[] = {
-	VDESC_NO_OFFSET
-};
-const struct vnodeop_desc vop_strategy_desc = {
-	1,
-	"vop_strategy",
-	0,
-	vop_strategy_vp_offsets,
-	VDESC_NO_OFFSET,
-	VDESC_NO_OFFSET,
-	VDESC_NO_OFFSET,
-	VDESC_NO_OFFSET,
-	NULL,
-};
-#ifdef VNODE_OP_NOINLINE
-int
-VOP_STRATEGY(bp)
-	struct buf *bp;
-{
-	struct vop_strategy_args a;
-	a.a_desc = VDESC(vop_strategy);
-	a.a_bp = bp;
-	return (VCALL(bp->b_vp, VOFFSET(vop_strategy), &a));
-}
-#endif
-
 const int vop_bwrite_vp_offsets[] = {
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_bwrite_desc = {
-	2,
+	1,
 	"vop_bwrite",
 	0,
 	vop_bwrite_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -125,21 +99,21 @@
 }
 #endif
 
 /* End of special cases */
 
 const int vop_lookup_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_lookup_args,a_dvp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_lookup_desc = {
-	3,
+	2,
 	"vop_lookup",
 	0,
 	vop_lookup_vp_offsets,
 	VOPARG_OFFSETOF(struct vop_lookup_args, a_vpp),
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_lookup_args, a_cnp),
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -156,21 +130,21 @@
 	a.a_cnp = cnp;
 	return (VCALL(dvp, VOFFSET(vop_lookup), &a));
 }
 #endif
 
 const int vop_create_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_create_args,a_dvp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_create_desc = {
-	4,
+	3,
 	"vop_create",
 	0 | VDESC_VP0_WILLPUT,
 	vop_create_vp_offsets,
 	VOPARG_OFFSETOF(struct vop_create_args, a_vpp),
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_create_args, a_cnp),
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -189,21 +163,21 @@
 	a.a_vap = vap;
 	return (VCALL(dvp, VOFFSET(vop_create), &a));
 }
 #endif
 
 const int vop_mknod_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_mknod_args,a_dvp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_mknod_desc = {
-	5,
+	4,
 	"vop_mknod",
 	0 | VDESC_VP0_WILLPUT,
 	vop_mknod_vp_offsets,
 	VOPARG_OFFSETOF(struct vop_mknod_args, a_vpp),
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_mknod_args, a_cnp),
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -222,21 +196,21 @@
 	a.a_vap = vap;
 	return (VCALL(dvp, VOFFSET(vop_mknod), &a));
 }
 #endif
 
 const int vop_open_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_open_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_open_desc = {
-	6,
+	5,
 	"vop_open",
 	0,
 	vop_open_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_open_args, a_cred),
 	VOPARG_OFFSETOF(struct vop_open_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -255,21 +229,21 @@
 	a.a_p = p;
 	return (VCALL(vp, VOFFSET(vop_open), &a));
 }
 #endif
 
 const int vop_close_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_close_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_close_desc = {
-	7,
+	6,
 	"vop_close",
 	0,
 	vop_close_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_close_args, a_cred),
 	VOPARG_OFFSETOF(struct vop_close_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -288,21 +262,21 @@
 	a.a_p = p;
 	return (VCALL(vp, VOFFSET(vop_close), &a));
 }
 #endif
 
 const int vop_access_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_access_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_access_desc = {
-	8,
+	7,
 	"vop_access",
 	0,
 	vop_access_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_access_args, a_cred),
 	VOPARG_OFFSETOF(struct vop_access_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -321,21 +295,21 @@
 	a.a_p = p;
 	return (VCALL(vp, VOFFSET(vop_access), &a));
 }
 #endif
 
 const int vop_getattr_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_getattr_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_getattr_desc = {
-	9,
+	8,
 	"vop_getattr",
 	0,
 	vop_getattr_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_getattr_args, a_cred),
 	VOPARG_OFFSETOF(struct vop_getattr_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -354,21 +328,21 @@
 	a.a_p = p;
 	return (VCALL(vp, VOFFSET(vop_getattr), &a));
 }
 #endif
 
 const int vop_setattr_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_setattr_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_setattr_desc = {
-	10,
+	9,
 	"vop_setattr",
 	0,
 	vop_setattr_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_setattr_args, a_cred),
 	VOPARG_OFFSETOF(struct vop_setattr_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -387,21 +361,21 @@
 	a.a_p = p;
 	return (VCALL(vp, VOFFSET(vop_setattr), &a));
 }
 #endif
 
 const int vop_read_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_read_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_read_desc = {
-	11,
+	10,
 	"vop_read",
 	0,
 	vop_read_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_read_args, a_cred),
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -420,21 +394,21 @@
 	a.a_cred = cred;
 	return (VCALL(vp, VOFFSET(vop_read), &a));
 }
 #endif
 
 const int vop_write_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_write_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_write_desc = {
-	12,
+	11,
 	"vop_write",
 	0,
 	vop_write_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_write_args, a_cred),
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -453,21 +427,21 @@
 	a.a_cred = cred;
 	return (VCALL(vp, VOFFSET(vop_write), &a));
 }
 #endif
 
 const int vop_ioctl_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_ioctl_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_ioctl_desc = {
-	13,
+	12,
 	"vop_ioctl",
 	0,
 	vop_ioctl_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_ioctl_args, a_cred),
 	VOPARG_OFFSETOF(struct vop_ioctl_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -490,21 +464,21 @@
 	a.a_p = p;
 	return (VCALL(vp, VOFFSET(vop_ioctl), &a));
 }
 #endif
 
 const int vop_fcntl_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_fcntl_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_fcntl_desc = {
-	14,
+	13,
 	"vop_fcntl",
 	0,
 	vop_fcntl_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_fcntl_args, a_cred),
 	VOPARG_OFFSETOF(struct vop_fcntl_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -527,21 +501,21 @@
 	a.a_p = p;
 	return (VCALL(vp, VOFFSET(vop_fcntl), &a));
 }
 #endif
 
 const int vop_poll_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_poll_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_poll_desc = {
-	15,
+	14,
 	"vop_poll",
 	0,
 	vop_poll_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_poll_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -558,21 +532,21 @@
 	a.a_p = p;
 	return (VCALL(vp, VOFFSET(vop_poll), &a));
 }
 #endif
 
 const int vop_kqfilter_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_kqfilter_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_kqfilter_desc = {
-	16,
+	15,
 	"vop_kqfilter",
 	0,
 	vop_kqfilter_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -587,21 +561,21 @@
 	a.a_kn = kn;
 	return (VCALL(vp, VOFFSET(vop_kqfilter), &a));
 }
 #endif
 
 const int vop_revoke_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_revoke_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_revoke_desc = {
-	17,
+	16,
 	"vop_revoke",
 	0,
 	vop_revoke_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -616,21 +590,21 @@
 	a.a_flags = flags;
 	return (VCALL(vp, VOFFSET(vop_revoke), &a));
 }
 #endif
 
 const int vop_mmap_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_mmap_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_mmap_desc = {
-	18,
+	17,
 	"vop_mmap",
 	0,
 	vop_mmap_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_mmap_args, a_cred),
 	VOPARG_OFFSETOF(struct vop_mmap_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -649,21 +623,21 @@
 	a.a_p = p;
 	return (VCALL(vp, VOFFSET(vop_mmap), &a));
 }
 #endif
 
 const int vop_fsync_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_fsync_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_fsync_desc = {
-	19,
+	18,
 	"vop_fsync",
 	0,
 	vop_fsync_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_fsync_args, a_cred),
 	VOPARG_OFFSETOF(struct vop_fsync_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -686,21 +660,21 @@
 	a.a_p = p;
 	return (VCALL(vp, VOFFSET(vop_fsync), &a));
 }
 #endif
 
 const int vop_seek_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_seek_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_seek_desc = {
-	20,
+	19,
 	"vop_seek",
 	0,
 	vop_seek_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_seek_args, a_cred),
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -720,21 +694,21 @@
 	return (VCALL(vp, VOFFSET(vop_seek), &a));
 }
 #endif
 
 const int vop_remove_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_remove_args,a_dvp),
 	VOPARG_OFFSETOF(struct vop_remove_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_remove_desc = {
-	21,
+	20,
 	"vop_remove",
 	0 | VDESC_VP0_WILLPUT | VDESC_VP1_WILLPUT,
 	vop_remove_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_remove_args, a_cnp),
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -752,21 +726,21 @@
 	return (VCALL(dvp, VOFFSET(vop_remove), &a));
 }
 #endif
 
 const int vop_link_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_link_args,a_dvp),
 	VOPARG_OFFSETOF(struct vop_link_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_link_desc = {
-	22,
+	21,
 	"vop_link",
 	0 | VDESC_VP0_WILLPUT,
 	vop_link_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_link_args, a_cnp),
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -786,21 +760,21 @@
 #endif
 
 const int vop_rename_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_rename_args,a_fdvp),
 	VOPARG_OFFSETOF(struct vop_rename_args,a_fvp),
 	VOPARG_OFFSETOF(struct vop_rename_args,a_tdvp),
 	VOPARG_OFFSETOF(struct vop_rename_args,a_tvp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_rename_desc = {
-	23,
+	22,
 	"vop_rename",
 	0 | VDESC_VP0_WILLRELE | VDESC_VP1_WILLRELE | VDESC_VP2_WILLPUT | VDESC_VP3_WILLPUT,
 	vop_rename_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_rename_args, a_fcnp),
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -823,21 +797,21 @@
 	a.a_tcnp = tcnp;
 	return (VCALL(fdvp, VOFFSET(vop_rename), &a));
 }
 #endif
 
 const int vop_mkdir_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_mkdir_args,a_dvp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_mkdir_desc = {
-	24,
+	23,
 	"vop_mkdir",
 	0 | VDESC_VP0_WILLPUT,
 	vop_mkdir_vp_offsets,
 	VOPARG_OFFSETOF(struct vop_mkdir_args, a_vpp),
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_mkdir_args, a_cnp),
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -857,21 +831,21 @@
 	return (VCALL(dvp, VOFFSET(vop_mkdir), &a));
 }
 #endif
 
 const int vop_rmdir_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_rmdir_args,a_dvp),
 	VOPARG_OFFSETOF(struct vop_rmdir_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_rmdir_desc = {
-	25,
+	24,
 	"vop_rmdir",
 	0 | VDESC_VP0_WILLPUT | VDESC_VP1_WILLPUT,
 	vop_rmdir_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_rmdir_args, a_cnp),
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -888,21 +862,21 @@
 	a.a_cnp = cnp;
 	return (VCALL(dvp, VOFFSET(vop_rmdir), &a));
 }
 #endif
 
 const int vop_symlink_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_symlink_args,a_dvp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_symlink_desc = {
-	26,
+	25,
 	"vop_symlink",
 	0 | VDESC_VP0_WILLPUT,
 	vop_symlink_vp_offsets,
 	VOPARG_OFFSETOF(struct vop_symlink_args, a_vpp),
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_symlink_args, a_cnp),
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -923,21 +897,21 @@
 	a.a_target = target;
 	return (VCALL(dvp, VOFFSET(vop_symlink), &a));
 }
 #endif
 
 const int vop_readdir_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_readdir_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_readdir_desc = {
-	27,
+	26,
 	"vop_readdir",
 	0,
 	vop_readdir_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_readdir_args, a_cred),
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -960,21 +934,21 @@
 	a.a_ncookies = ncookies;
 	return (VCALL(vp, VOFFSET(vop_readdir), &a));
 }
 #endif
 
 const int vop_readlink_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_readlink_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_readlink_desc = {
-	28,
+	27,
 	"vop_readlink",
 	0,
 	vop_readlink_vp_offsets,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_readlink_args, a_cred),
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -991,21 +965,21 @@
 	a.a_cred = cred;
 	return (VCALL(vp, VOFFSET(vop_readlink), &a));
 }
 #endif
 
 const int vop_abortop_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_abortop_args,a_dvp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_abortop_desc = {
-	29,
+	28,
 	"vop_abortop",
 	0,
 	vop_abortop_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_abortop_args, a_cnp),
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -1020,21 +994,21 @@
 	a.a_cnp = cnp;
 	return (VCALL(dvp, VOFFSET(vop_abortop), &a));
 }
 #endif
 
 const int vop_inactive_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_inactive_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_inactive_desc = {
-	30,
+	29,
 	"vop_inactive",
 	0 | VDESC_VP0_WILLUNLOCK,
 	vop_inactive_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_inactive_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -1049,21 +1023,21 @@
 	a.a_p = p;
 	return (VCALL(vp, VOFFSET(vop_inactive), &a));
 }
 #endif
 
 const int vop_reclaim_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_reclaim_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_reclaim_desc = {
-	31,
+	30,
 	"vop_reclaim",
 	0,
 	vop_reclaim_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VOPARG_OFFSETOF(struct vop_reclaim_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -1078,21 +1052,21 @@
 	a.a_p = p;
 	return (VCALL(vp, VOFFSET(vop_reclaim), &a));
 }
 #endif
 
 const int vop_lock_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_lock_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_lock_desc = {
-	32,
+	31,
 	"vop_lock",
 	0,
 	vop_lock_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -1107,21 +1081,21 @@
 	a.a_flags = flags;
 	return (VCALL(vp, VOFFSET(vop_lock), &a));
 }
 #endif
 
 const int vop_unlock_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_unlock_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_unlock_desc = {
-	33,
+	32,
 	"vop_unlock",
 	0,
 	vop_unlock_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -1136,21 +1110,21 @@
 	a.a_flags = flags;
 	return (VCALL(vp, VOFFSET(vop_unlock), &a));
 }
 #endif
 
 const int vop_bmap_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_bmap_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_bmap_desc = {
-	34,
+	33,
 	"vop_bmap",
 	0,
 	vop_bmap_vp_offsets,
 	VOPARG_OFFSETOF(struct vop_bmap_args, a_vpp),
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
 	NULL,
 };
 #ifdef VNODE_OP_NOINLINE
@@ -1166,20 +1140,49 @@
 	a.a_desc = VDESC(vop_bmap);
 	a.a_vp = vp;
 	a.a_bn = bn;
 	a.a_vpp = vpp;
 	a.a_bnp = bnp;
 	a.a_runp = runp;
 	return (VCALL(vp, VOFFSET(vop_bmap), &a));
 }
 #endif
 
+const int vop_strategy_vp_offsets[] = {
+	VOPARG_OFFSETOF(struct vop_strategy_args,a_vp),
+	VDESC_NO_OFFSET
+};
+const struct vnodeop_desc vop_strategy_desc = {
+	34,
+	"vop_strategy",
+	0,
+	vop_strategy_vp_offsets,
+	VDESC_NO_OFFSET,
+	VDESC_NO_OFFSET,
+	VDESC_NO_OFFSET,
+	VDESC_NO_OFFSET,
+	NULL,
+};
+#ifdef VNODE_OP_NOINLINE
+int
+VOP_STRATEGY(vp, bp)
+	struct vnode *vp;
+	struct buf *bp;
+{
+	struct vop_strategy_args a;
+	a.a_desc = VDESC(vop_strategy);
+	a.a_vp = vp;
+	a.a_bp = bp;
+	return (VCALL(vp, VOFFSET(vop_strategy), &a));
+}
+#endif
+
 const int vop_print_vp_offsets[] = {
 	VOPARG_OFFSETOF(struct vop_print_args,a_vp),
 	VDESC_NO_OFFSET
 };
 const struct vnodeop_desc vop_print_desc = {
 	35,
 	"vop_print",
 	0,
 	vop_print_vp_offsets,
 	VDESC_NO_OFFSET,
@@ -1659,21 +1662,20 @@
 	a.a_offhi = offhi;
 	a.a_flags = flags;
 	return (VCALL(vp, VOFFSET(vop_putpages), &a));
 }
 #endif
 
 /* End of special cases. */
 
 const struct vnodeop_desc * const vfs_op_descs[] = {
 	&vop_default_desc,	/* MUST BE FIRST */
-	&vop_strategy_desc,	/* XXX: SPECIAL CASE */
 	&vop_bwrite_desc,	/* XXX: SPECIAL CASE */
 
 	&vop_lookup_desc,
 	&vop_create_desc,
 	&vop_mknod_desc,
 	&vop_open_desc,
 	&vop_close_desc,
 	&vop_access_desc,
 	&vop_getattr_desc,
 	&vop_setattr_desc,
@@ -1694,20 +1696,21 @@
 	&vop_rmdir_desc,
 	&vop_symlink_desc,
 	&vop_readdir_desc,
 	&vop_readlink_desc,
 	&vop_abortop_desc,
 	&vop_inactive_desc,
 	&vop_reclaim_desc,
 	&vop_lock_desc,
 	&vop_unlock_desc,
 	&vop_bmap_desc,
+	&vop_strategy_desc,
 	&vop_print_desc,
 	&vop_islocked_desc,
 	&vop_pathconf_desc,
 	&vop_advlock_desc,
 	&vop_blkatoff_desc,
 	&vop_valloc_desc,
 	&vop_balloc_desc,
 	&vop_reallocblks_desc,
 	&vop_vfree_desc,
 	&vop_truncate_desc,
Index: kern/vnode_if.sh
===================================================================
RCS file: /cvsroot/src/sys/kern/vnode_if.sh,v
retrieving revision 1.33
diff -u -1 -0 -r1.33 vnode_if.sh
--- kern/vnode_if.sh	7 Aug 2003 16:32:05 -0000	1.33
+++ kern/vnode_if.sh	19 Jan 2004 18:53:58 -0000
@@ -229,22 +229,20 @@
 BEGIN	{
 	arg0special="";
 	vops = 1; # start at 1, to count the 'default' op
 }
 END	{
 	printf("\n/* Special cases: */\n#include <sys/buf.h>\n");
 	argc=1;
 	argtype[0]="struct buf *";
 	argname[0]="bp";
 	arg0special="->b_vp";
-	name="vop_strategy";
-	doit();
 	name="vop_bwrite";
 	doit();
 
 	printf("\n#define VNODE_OPS_COUNT\t%d\n", vops);
 }
 '"$awk_parser" | sed -e "$anal_retentive"
 
 # End stuff
 echo '
 /* End of special cases. */'
@@ -383,40 +381,37 @@
 BEGIN	{
 	printf("\n/* Special cases: */\n");
 	# start from 1 (vop_default is at 0)
 	vop_offset=1;
 	argc=1;
 	argdir[0]="IN";
 	argtype[0]="struct buf *";
 	argname[0]="bp";
 	arg0special="->b_vp";
 	willrele[0]=0;
-	name="vop_strategy";
-	doit();
 	name="vop_bwrite";
 	doit();
 	printf("\n/* End of special cases */\n");
 
 	arg0special="";
 }
 '"$awk_parser" | sed -e "$anal_retentive"
 
 # End stuff
 echo '
 /* End of special cases. */'
 
 # Add the vfs_op_descs array to the C file.
 # Begin stuff
 echo '
 const struct vnodeop_desc * const vfs_op_descs[] = {
 	&vop_default_desc,	/* MUST BE FIRST */
-	&vop_strategy_desc,	/* XXX: SPECIAL CASE */
 	&vop_bwrite_desc,	/* XXX: SPECIAL CASE */
 '
 
 # Body stuff
 sed -e "$sed_prep" $src | $awk '
 function doit() {
 	printf("\t&%s_desc,\n", name);
 }
 '"$awk_parser"
 
Index: kern/vnode_if.src
===================================================================
RCS file: /cvsroot/src/sys/kern/vnode_if.src,v
retrieving revision 1.36
diff -u -1 -0 -r1.36 vnode_if.src
--- kern/vnode_if.src	17 Nov 2003 11:16:10 -0000	1.36
+++ kern/vnode_if.src	19 Jan 2004 18:53:58 -0000
@@ -427,25 +427,26 @@
 #
 vop_bmap {
 	IN struct vnode *vp;
 	IN daddr_t bn;
 	OUT struct vnode **vpp;
 	IN daddr_t *bnp;
 	OUT int *runp;
 };
 
 #
-# Needs work: no vp?
+#% strategy   vp      = = =
 #
-#vop_strategy {
-#	IN struct buf *bp;
-#};
+vop_strategy {
+	IN struct vnode *vp;
+	IN struct buf *bp;
+};
 
 #
 #% print      vp      = = =
 #
 vop_print {
 	IN struct vnode *vp;
 };
 
 #
 #% islocked   vp      = = =
Index: miscfs/deadfs/dead_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/deadfs/dead_vnops.c,v
retrieving revision 1.33
diff -u -1 -0 -r1.33 dead_vnops.c
--- miscfs/deadfs/dead_vnops.c	7 Aug 2003 16:32:32 -0000	1.33
+++ miscfs/deadfs/dead_vnops.c	19 Jan 2004 18:53:58 -0000
@@ -264,28 +264,29 @@
 
 /*
  * Just call the device strategy routine
  */
 int
 dead_strategy(v)
 	void *v;
 {
 
 	struct vop_strategy_args /* {
+		struct vnode *a_vp;
 		struct buf *a_bp;
 	} */ *ap = v;
-	if (ap->a_bp->b_vp == NULL || !chkvnlock(ap->a_bp->b_vp)) {
+	if (ap->a_vp == NULL || !chkvnlock(ap->a_vp)) {
 		ap->a_bp->b_flags |= B_ERROR;
 		biodone(ap->a_bp);
 		return (EIO);
 	}
-	return (VOP_STRATEGY(ap->a_bp));
+	return (VOP_STRATEGY(ap->a_vp, ap->a_bp));
 }
 
 /*
  * Wait until the vnode has finished changing state.
  */
 int
 dead_lock(v)
 	void *v;
 {
 	struct vop_lock_args /* {
Index: miscfs/genfs/genfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/genfs/genfs_vnops.c,v
retrieving revision 1.84
diff -u -1 -0 -r1.84 genfs_vnops.c
--- miscfs/genfs/genfs_vnops.c	10 Jan 2004 14:39:50 -0000	1.84
+++ miscfs/genfs/genfs_vnops.c	19 Jan 2004 18:53:59 -0000
@@ -819,21 +819,21 @@
 		    dev_bshift);
 
 		UVMHIST_LOG(ubchist,
 		    "bp %p offset 0x%x bcount 0x%x blkno 0x%x",
 		    bp, offset, iobytes, bp->b_blkno);
 
 		if (async)
 			BIO_SETPRIO(bp, BPRIO_TIMELIMITED);
 		else
 			BIO_SETPRIO(bp, BPRIO_TIMECRITICAL);
-		VOP_STRATEGY(bp);
+		VOP_STRATEGY(bp->b_vp, bp);
 	}
 
 loopdone:
 	if (skipbytes) {
 		s = splbio();
 		if (error) {
 			mbp->b_flags |= B_ERROR;
 			mbp->b_error = error;
 		}
 		mbp->b_resid -= skipbytes;
@@ -1492,21 +1492,21 @@
 		    dev_bshift);
 		UVMHIST_LOG(ubchist,
 		    "vp %p offset 0x%x bcount 0x%x blkno 0x%x",
 		    vp, offset, bp->b_bcount, bp->b_blkno);
 		if (curproc == uvm.pagedaemon_proc)
 			BIO_SETPRIO(bp, BPRIO_TIMELIMITED);
 		else if (async)
 			BIO_SETPRIO(bp, BPRIO_TIMENONCRITICAL);
 		else
 			BIO_SETPRIO(bp, BPRIO_TIMECRITICAL);
-		VOP_STRATEGY(bp);
+		VOP_STRATEGY(bp->b_vp, bp);
 	}
 	if (skipbytes) {
 		UVMHIST_LOG(ubchist, "skipbytes %d", skipbytes, 0,0,0);
 		s = splbio();
 		if (error) {
 			mbp->b_flags |= B_ERROR;
 			mbp->b_error = error;
 		}
 		mbp->b_resid -= skipbytes;
 		if (mbp->b_resid == 0) {
Index: miscfs/genfs/layer_extern.h
===================================================================
RCS file: /cvsroot/src/sys/miscfs/genfs/layer_extern.h,v
retrieving revision 1.10
diff -u -1 -0 -r1.10 layer_extern.h
--- miscfs/genfs/layer_extern.h	4 Dec 2003 19:38:24 -0000	1.10
+++ miscfs/genfs/layer_extern.h	19 Jan 2004 18:53:59 -0000
@@ -93,21 +93,20 @@
 int	layerfs_checkexp __P((struct mount *, struct mbuf *, int *,
 			   struct ucred **));
 int	layerfs_vptofh __P((struct vnode *, struct fid *));
 
 /* VOP routines */
 int	layer_bypass __P((void *));
 int	layer_getattr __P((void *));
 int	layer_inactive __P((void *));
 int	layer_reclaim __P((void *));
 int	layer_print __P((void *));
-int	layer_strategy __P((void *));
 int	layer_bwrite __P((void *));
 int	layer_bmap __P((void *));
 int	layer_lock __P((void *));
 int	layer_unlock __P((void *));
 int	layer_islocked __P((void *));
 int	layer_fsync __P((void *));
 int	layer_lookup __P((void *));
 int	layer_setattr __P((void *));
 int	layer_access __P((void *));
 int	layer_open __P((void *));
Index: miscfs/genfs/layer_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/genfs/layer_vnops.c,v
retrieving revision 1.13
diff -u -1 -0 -r1.13 layer_vnops.c
--- miscfs/genfs/layer_vnops.c	30 Nov 2003 20:53:48 -0000	1.13
+++ miscfs/genfs/layer_vnops.c	19 Jan 2004 18:53:59 -0000
@@ -825,47 +825,21 @@
 {
 	struct vop_print_args /* {
 		struct vnode *a_vp;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
 	printf ("\ttag VT_LAYERFS, vp=%p, lowervp=%p\n", vp, LAYERVPTOLOWERVP(vp));
 	return (0);
 }
 
 /*
- * XXX - vop_strategy must be hand coded because it has no
- * vnode in its arguments.
- * This goes away with a merged VM/buffer cache.
- */
-int
-layer_strategy(v)
-	void *v;
-{
-	struct vop_strategy_args /* {
-		struct buf *a_bp;
-	} */ *ap = v;
-	struct buf *bp = ap->a_bp;
-	int error;
-	struct vnode *savedvp;
-
-	savedvp = bp->b_vp;
-	bp->b_vp = LAYERVPTOLOWERVP(bp->b_vp);
-
-	error = VOP_STRATEGY(bp);
-
-	bp->b_vp = savedvp;
-
-	return (error);
-}
-
-/*
- * XXX - like vop_strategy, vop_bwrite must be hand coded because it has no
+ * XXX - vop_bwrite must be hand coded because it has no
  * vnode in its arguments.
  * This goes away with a merged VM/buffer cache.
  */
 int
 layer_bwrite(v)
 	void *v;
 {
 	struct vop_bwrite_args /* {
 		struct buf *a_bp;
 	} */ *ap = v;
Index: miscfs/nullfs/null_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/nullfs/null_vnops.c,v
retrieving revision 1.27
diff -u -1 -0 -r1.27 null_vnops.c
--- miscfs/nullfs/null_vnops.c	7 Aug 2003 16:32:39 -0000	1.27
+++ miscfs/nullfs/null_vnops.c	19 Jan 2004 18:53:59 -0000
@@ -232,20 +232,19 @@
 	{ &vop_lock_desc,     layer_lock },
 	{ &vop_unlock_desc,   layer_unlock },
 	{ &vop_islocked_desc, layer_islocked },
 	{ &vop_fsync_desc,    layer_fsync },
 	{ &vop_inactive_desc, layer_inactive },
 	{ &vop_reclaim_desc,  layer_reclaim },
 	{ &vop_print_desc,    layer_print },
 
 	{ &vop_open_desc,     layer_open },	/* mount option handling */
 
-	{ &vop_strategy_desc, layer_strategy },
 	{ &vop_bwrite_desc,   layer_bwrite },
 	{ &vop_bmap_desc,     layer_bmap },
 	{ &vop_getpages_desc, layer_getpages },
 	{ &vop_putpages_desc, layer_putpages },
 
 	{ NULL, NULL }
 };
 const struct vnodeopv_desc null_vnodeop_opv_desc =
 	{ &null_vnodeop_p, null_vnodeop_entries };
Index: miscfs/overlay/overlay_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/overlay/overlay_vnops.c,v
retrieving revision 1.10
diff -u -1 -0 -r1.10 overlay_vnops.c
--- miscfs/overlay/overlay_vnops.c	7 Aug 2003 16:32:40 -0000	1.10
+++ miscfs/overlay/overlay_vnops.c	19 Jan 2004 18:53:59 -0000
@@ -155,20 +155,19 @@
 	{ &vop_lock_desc,     layer_lock },
 	{ &vop_unlock_desc,   layer_unlock },
 	{ &vop_islocked_desc, layer_islocked },
 	{ &vop_fsync_desc,    layer_fsync },
 	{ &vop_inactive_desc, layer_inactive },
 	{ &vop_reclaim_desc,  layer_reclaim },
 	{ &vop_print_desc,    layer_print },
 
 	{ &vop_open_desc,     layer_open },	/* mount option handling */
 
-	{ &vop_strategy_desc, layer_strategy },
 	{ &vop_bwrite_desc,   layer_bwrite },
 	{ &vop_bmap_desc,     layer_bmap },
 	{ &vop_getpages_desc, layer_getpages },
 	{ &vop_putpages_desc, layer_putpages },
 
 	{ NULL, NULL }
 };
 const struct vnodeopv_desc overlay_vnodeop_opv_desc =
 	{ &overlay_vnodeop_p, overlay_vnodeop_entries };
Index: miscfs/specfs/spec_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/specfs/spec_vnops.c,v
retrieving revision 1.75
diff -u -1 -0 -r1.75 spec_vnops.c
--- miscfs/specfs/spec_vnops.c	10 Dec 2003 11:40:12 -0000	1.75
+++ miscfs/specfs/spec_vnops.c	19 Jan 2004 18:54:00 -0000
@@ -576,36 +576,34 @@
 }
 
 /*
  * Just call the device strategy routine
  */
 int
 spec_strategy(v)
 	void *v;
 {
 	struct vop_strategy_args /* {
+		struct vnode *a_vp;
 		struct buf *a_bp;
 	} */ *ap = v;
 	struct buf *bp;
-	const struct bdevsw *bdev;
 
 	bp = ap->a_bp;
 	if (!(bp->b_flags & B_READ) &&
 	    (LIST_FIRST(&bp->b_dep)) != NULL && bioops.io_start)
 		(*bioops.io_start)(bp);
-	bdev = bdevsw_lookup(bp->b_dev);
-	if (bdev != NULL) {
 #if NFSS > 0
-		fss_cow_hook(bp);
+	fss_cow_hook(bp);
 #endif
-		(*bdev->d_strategy)(bp);
-	}
+	DEV_STRATEGY(bp);
+
 	return (0);
 }
 
 int
 spec_inactive(v)
 	void *v;
 {
 	struct vop_inactive_args /* {
 		struct vnode *a_vp;
 		struct proc *a_p;
Index: miscfs/umapfs/umap_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/umapfs/umap_vnops.c,v
retrieving revision 1.23
diff -u -1 -0 -r1.23 umap_vnops.c
--- miscfs/umapfs/umap_vnops.c	7 Aug 2003 16:32:46 -0000	1.23
+++ miscfs/umapfs/umap_vnops.c	19 Jan 2004 18:54:00 -0000
@@ -78,21 +78,20 @@
 	{ &vop_lock_desc,	layer_lock },
 	{ &vop_unlock_desc,	layer_unlock },
 	{ &vop_islocked_desc,	layer_islocked },
 	{ &vop_fsync_desc,	layer_fsync },
 	{ &vop_inactive_desc,	layer_inactive },
 	{ &vop_reclaim_desc,	layer_reclaim },
 	{ &vop_open_desc,	layer_open },
 	{ &vop_setattr_desc,	layer_setattr },
 	{ &vop_access_desc,	layer_access },
 
-	{ &vop_strategy_desc,	layer_strategy },
 	{ &vop_bwrite_desc,	layer_bwrite },
 	{ &vop_bmap_desc,	layer_bmap },
 	{ &vop_getpages_desc,	layer_getpages },
 	{ &vop_putpages_desc,	layer_putpages },
 
 	{ NULL, NULL }
 };
 const struct vnodeopv_desc umapfs_vnodeop_opv_desc =
 	{ &umap_vnodeop_p, umap_vnodeop_entries };
 
Index: sys/conf.h
===================================================================
RCS file: /cvsroot/src/sys/sys/conf.h,v
retrieving revision 1.114
diff -u -1 -0 -r1.114 conf.h
--- sys/conf.h	16 Oct 2003 12:02:58 -0000	1.114
+++ sys/conf.h	19 Jan 2004 18:54:00 -0000
@@ -82,20 +82,28 @@
 	void		(*d_stop)(struct tty *, int);
 	struct tty *	(*d_tty)(dev_t);
 	int		(*d_poll)(dev_t, int, struct proc *);
 	paddr_t		(*d_mmap)(dev_t, off_t, int);
 	int		(*d_kqfilter)(dev_t dev, struct knote *kn);
 	int		d_type;
 };
 
 #ifdef _KERNEL
 
+#define DEV_STRATEGY(bp) \
+	do { \
+		const struct bdevsw *bdev = bdevsw_lookup((bp)->b_dev); \
+		if (bdev == NULL) \
+			panic("DEV_STRATEGY: block device not found"); \
+		(*bdev->d_strategy)((bp)); \
+	} while (/*CONSTCOND*/0)
+
 int devsw_attach(const char *, const struct bdevsw *, int *,
 		 const struct cdevsw *, int *);
 void devsw_detach(const struct bdevsw *, const struct cdevsw *);
 const struct bdevsw *bdevsw_lookup(dev_t);
 const struct cdevsw *cdevsw_lookup(dev_t);
 int bdevsw_lookup_major(const struct bdevsw *);
 int cdevsw_lookup_major(const struct cdevsw *);
 
 #define	dev_type_open(n)	int n (dev_t, int, int, struct proc *)
 #define	dev_type_close(n)	int n (dev_t, int, int, struct proc *)
Index: sys/vnode_if.h
===================================================================
RCS file: /cvsroot/src/sys/sys/vnode_if.h,v
retrieving revision 1.44
diff -u -1 -0 -r1.44 vnode_if.h
--- sys/vnode_if.h	7 Aug 2003 16:34:23 -0000	1.44
+++ sys/vnode_if.h	19 Jan 2004 18:54:03 -0000
@@ -1,20 +1,20 @@
-/*	$NetBSD: vnode_if.h,v 1.44 2003/08/07 16:34:23 agc Exp $	*/
+/*	$NetBSD$	*/
 
 /*
  * Warning: This file is generated automatically.
  * (Modifications made here may easily be lost!)
  *
  * Created from the file:
- *	NetBSD: vnode_if.src,v 1.33 2003/04/10 20:35:36 jdolecek Exp 
+ *	NetBSD: vnode_if.src,v 1.36 2003/11/17 11:16:10 wiz Exp 
  * by the script:
- *	NetBSD: vnode_if.sh,v 1.30 2001/11/12 14:34:24 lukem Exp 
+ *	NetBSD: vnode_if.sh,v 1.33 2003/08/07 16:32:05 agc Exp 
  */
 
 /*
  * Copyright (c) 1992, 1993, 1994, 1995
  *	The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
@@ -1088,20 +1088,47 @@
 	a.a_desc = VDESC(vop_bmap);
 	a.a_vp = vp;
 	a.a_bn = bn;
 	a.a_vpp = vpp;
 	a.a_bnp = bnp;
 	a.a_runp = runp;
 	return (VCALL(vp, VOFFSET(vop_bmap), &a));
 }
 #endif
 
+struct vop_strategy_args {
+	const struct vnodeop_desc *a_desc;
+	struct vnode *a_vp;
+	struct buf *a_bp;
+};
+extern const struct vnodeop_desc vop_strategy_desc;
+#ifndef VNODE_OP_NOINLINE
+static __inline
+#endif
+int VOP_STRATEGY(struct vnode *, struct buf *)
+#ifndef VNODE_OP_NOINLINE
+__attribute__((__unused__))
+#endif
+;
+#ifndef VNODE_OP_NOINLINE
+static __inline int VOP_STRATEGY(vp, bp)
+	struct vnode *vp;
+	struct buf *bp;
+{
+	struct vop_strategy_args a;
+	a.a_desc = VDESC(vop_strategy);
+	a.a_vp = vp;
+	a.a_bp = bp;
+	return (VCALL(vp, VOFFSET(vop_strategy), &a));
+}
+#endif
+
 struct vop_print_args {
 	const struct vnodeop_desc *a_desc;
 	struct vnode *a_vp;
 };
 extern const struct vnodeop_desc vop_print_desc;
 #ifndef VNODE_OP_NOINLINE
 static __inline
 #endif
 int VOP_PRINT(struct vnode *)
 #ifndef VNODE_OP_NOINLINE
@@ -1578,44 +1605,20 @@
 	a.a_offlo = offlo;
 	a.a_offhi = offhi;
 	a.a_flags = flags;
 	return (VCALL(vp, VOFFSET(vop_putpages), &a));
 }
 #endif
 
 /* Special cases: */
 #include <sys/buf.h>
 
-struct vop_strategy_args {
-	const struct vnodeop_desc *a_desc;
-	struct buf *a_bp;
-};
-extern const struct vnodeop_desc vop_strategy_desc;
-#ifndef VNODE_OP_NOINLINE
-static __inline
-#endif
-int VOP_STRATEGY(struct buf *)
-#ifndef VNODE_OP_NOINLINE
-__attribute__((__unused__))
-#endif
-;
-#ifndef VNODE_OP_NOINLINE
-static __inline int VOP_STRATEGY(bp)
-	struct buf *bp;
-{
-	struct vop_strategy_args a;
-	a.a_desc = VDESC(vop_strategy);
-	a.a_bp = bp;
-	return (VCALL(bp->b_vp, VOFFSET(vop_strategy), &a));
-}
-#endif
-
 struct vop_bwrite_args {
 	const struct vnodeop_desc *a_desc;
 	struct buf *a_bp;
 };
 extern const struct vnodeop_desc vop_bwrite_desc;
 #ifndef VNODE_OP_NOINLINE
 static __inline
 #endif
 int VOP_BWRITE(struct buf *)
 #ifndef VNODE_OP_NOINLINE
Index: ufs/ext2fs/ext2fs_bmap.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_bmap.c,v
retrieving revision 1.13
diff -u -1 -0 -r1.13 ext2fs_bmap.c
--- ufs/ext2fs/ext2fs_bmap.c	5 Oct 2003 17:48:49 -0000	1.13
+++ ufs/ext2fs/ext2fs_bmap.c	19 Jan 2004 18:54:03 -0000
@@ -230,21 +230,21 @@
 			trace(TR_BREADHIT, pack(vp, size), metalbn);
 		}
 #ifdef DIAGNOSTIC
 		else if (!daddr)
 			panic("ext2fs_bmaparry: indirect block not in cache");
 #endif
 		else {
 			trace(TR_BREADMISS, pack(vp, size), metalbn);
 			bp->b_blkno = blkptrtodb(ump, daddr);
 			bp->b_flags |= B_READ;
-			VOP_STRATEGY(bp);
+			VOP_STRATEGY(vp, bp);
 			curproc->p_stats->p_ru.ru_inblock++;	/* XXX */
 			if ((error = biowait(bp)) != 0) {
 				brelse(bp);
 				return (error);
 			}
 		}
 
 		/* XXX ondisk32 */
 		daddr = fs2h32(((int32_t *)bp->b_data)[xap->in_off]);
 		if (num == 1 && daddr && runp)
Index: ufs/ext2fs/ext2fs_inode.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_inode.c,v
retrieving revision 1.38
diff -u -1 -0 -r1.38 ext2fs_inode.c
--- ufs/ext2fs/ext2fs_inode.c	5 Nov 2003 10:18:38 -0000	1.38
+++ ufs/ext2fs/ext2fs_inode.c	19 Jan 2004 18:54:04 -0000
@@ -452,21 +452,21 @@
 	if (bp->b_flags & (B_DONE | B_DELWRI)) {
 		/* Braces must be here in case trace evaluates to nothing. */
 		trace(TR_BREADHIT, pack(vp, fs->e2fs_bsize), lbn);
 	} else {
 		trace(TR_BREADMISS, pack(vp, fs->e2fs_bsize), lbn);
 		curproc->p_stats->p_ru.ru_inblock++;	/* pay for read */
 		bp->b_flags |= B_READ;
 		if (bp->b_bcount > bp->b_bufsize)
 			panic("ext2fs_indirtrunc: bad buffer size");
 		bp->b_blkno = dbn;
-		VOP_STRATEGY(bp);
+		VOP_STRATEGY(vp, bp);
 		error = biowait(bp);
 	}
 	if (error) {
 		brelse(bp);
 		*countp = 0;
 		return (error);
 	}
 
 	bap = (int32_t *)bp->b_data;	/* XXX ondisk32 */
 	if (lastbn >= 0) {
Index: ufs/ffs/ffs_inode.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_inode.c,v
retrieving revision 1.61
diff -u -1 -0 -r1.61 ffs_inode.c
--- ufs/ffs/ffs_inode.c	10 Jan 2004 14:39:51 -0000	1.61
+++ ufs/ffs/ffs_inode.c	19 Jan 2004 18:54:04 -0000
@@ -557,21 +557,21 @@
 		/* Braces must be here in case trace evaluates to nothing. */
 		trace(TR_BREADHIT, pack(vp, fs->fs_bsize), lbn);
 	} else {
 		trace(TR_BREADMISS, pack(vp, fs->fs_bsize), lbn);
 		curproc->p_stats->p_ru.ru_inblock++;	/* pay for read */
 		bp->b_flags |= B_READ;
 		if (bp->b_bcount > bp->b_bufsize)
 			panic("ffs_indirtrunc: bad buffer size");
 		bp->b_blkno = dbn;
 		BIO_SETPRIO(bp, BPRIO_TIMECRITICAL);
-		VOP_STRATEGY(bp);
+		VOP_STRATEGY(vp, bp);
 		error = biowait(bp);
 	}
 	if (error) {
 		brelse(bp);
 		*countp = 0;
 		return (error);
 	}
 
 	if (ip->i_ump->um_fstype == UFS1)
 		bap1 = (int32_t *)bp->b_data;
Index: ufs/lfs/lfs_balloc.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_balloc.c,v
retrieving revision 1.47
diff -u -1 -0 -r1.47 lfs_balloc.c
--- ufs/lfs/lfs_balloc.c	30 Dec 2003 12:33:24 -0000	1.47
+++ ufs/lfs/lfs_balloc.c	19 Jan 2004 18:54:04 -0000
@@ -260,21 +260,21 @@
 			idaddr = ip->i_ffs1_ib[indirs[0].in_off];
 			for (i = 1; i < num; ++i) {
 				ibp = getblk(vp, indirs[i].in_lbn,
 				    fs->lfs_bsize, 0,0);
 				if (!indirs[i].in_exists) {
 					clrbuf(ibp);
 					ibp->b_blkno = UNWRITTEN;
 				} else if (!(ibp->b_flags & (B_DELWRI | B_DONE))) {
 					ibp->b_blkno = fsbtodb(fs, idaddr);
 					ibp->b_flags |= B_READ;
-					VOP_STRATEGY(ibp);
+					VOP_STRATEGY(vp, ibp);
 					biowait(ibp);
 				}
 				/*
 				 * This block exists, but the next one may not.
 				 * If that is the case mark it UNWRITTEN to keep
 				 * the accounting straight.
 				 */
 				/* XXX ondisk32 */
 				if (((int32_t *)ibp->b_data)[indirs[i].in_off] == 0)
 					((int32_t *)ibp->b_data)[indirs[i].in_off] =
@@ -337,21 +337,21 @@
 		if (iosize == fs->lfs_bsize)
 			/* Optimization: I/O is unnecessary. */
 			bp->b_blkno = daddr;
 		else {
 			/*
 			 * We need to read the block to preserve the
 			 * existing bytes.
 			 */
 			bp->b_blkno = daddr;
 			bp->b_flags |= B_READ;
-			VOP_STRATEGY(bp);
+			VOP_STRATEGY(vp, bp);
 			return (biowait(bp));
 		}
 	}
 	
 	return (0);
 }
 
 /* VOP_BWRITE 1 time */
 int
 lfs_fragextend(struct vnode *vp, int osize, int nsize, daddr_t lbn, struct buf **bpp, struct ucred *cred)
Index: ufs/lfs/lfs_inode.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_inode.c,v
retrieving revision 1.81
diff -u -1 -0 -r1.81 lfs_inode.c
--- ufs/lfs/lfs_inode.c	30 Dec 2003 12:33:24 -0000	1.81
+++ ufs/lfs/lfs_inode.c	19 Jan 2004 18:54:11 -0000
@@ -672,21 +672,21 @@
 	if (bp->b_flags & (B_DONE | B_DELWRI)) {
 		/* Braces must be here in case trace evaluates to nothing. */
 		trace(TR_BREADHIT, pack(vp, fs->lfs_bsize), lbn);
 	} else {
 		trace(TR_BREADMISS, pack(vp, fs->lfs_bsize), lbn);
 		p->p_stats->p_ru.ru_inblock++;	/* pay for read */
 		bp->b_flags |= B_READ;
 		if (bp->b_bcount > bp->b_bufsize)
 			panic("lfs_indirtrunc: bad buffer size");
 		bp->b_blkno = fsbtodb(fs, dbn);
-		VOP_STRATEGY(bp);
+		VOP_STRATEGY(vp, bp);
 		error = biowait(bp);
 	}
 	if (error) {
 		brelse(bp);
 		*countp = *rcountp = 0;
 		return (error);
 	}
 
 	bap = (int32_t *)bp->b_data;	/* XXX ondisk32 */
 	if (lastbn >= 0) {
Index: ufs/lfs/lfs_segment.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_segment.c,v
retrieving revision 1.147
diff -u -1 -0 -r1.147 lfs_segment.c
--- ufs/lfs/lfs_segment.c	10 Jan 2004 14:39:51 -0000	1.147
+++ ufs/lfs/lfs_segment.c	19 Jan 2004 18:54:25 -0000
@@ -2001,20 +2001,21 @@
 			i--;
 		}
 		if (fs->lfs_sp->seg_flags & SEGM_SYNC)
 			BIO_SETPRIO(cbp, BPRIO_TIMECRITICAL);
 		else
 			BIO_SETPRIO(cbp, BPRIO_TIMELIMITED);
 		s = splbio();
 		V_INCR_NUMOUTPUT(devvp);
 		splx(s);
 		vop_strategy_a.a_desc = VDESC(vop_strategy);
+		vop_strategy_a.a_vp = cbp->b_vp;
 		vop_strategy_a.a_bp = cbp;
 		(strategy)(&vop_strategy_a);
 		curproc->p_stats->p_ru.ru_oublock++;
 	}
 
 	if (lfs_dostats) {
 		++lfs_stats.psegwrites;
 		lfs_stats.blocktot += nblocks - 1;
 		if (fs->lfs_sp->seg_flags & SEGM_SYNC)
 			++lfs_stats.psyncwrites;
@@ -2065,20 +2066,21 @@
 	bp->b_dev = i_dev;
 	bp->b_flags |= B_BUSY | B_CALL | B_ASYNC;
 	bp->b_flags &= ~(B_DONE | B_ERROR | B_READ | B_DELWRI);
 	bp->b_iodone = lfs_supercallback;
 
 	if (fs->lfs_sp != NULL && fs->lfs_sp->seg_flags & SEGM_SYNC)
 		BIO_SETPRIO(bp, BPRIO_TIMECRITICAL);
 	else
 		BIO_SETPRIO(bp, BPRIO_TIMELIMITED);
 	vop_strategy_a.a_desc = VDESC(vop_strategy);
+	vop_strategy_a.a_vp = bp->b_vp;
 	vop_strategy_a.a_bp = bp;
 	curproc->p_stats->p_ru.ru_oublock++;
 	s = splbio();
 	V_INCR_NUMOUTPUT(bp->b_vp);
 	splx(s);
 	++fs->lfs_iocount;
 	(strategy)(&vop_strategy_a);
 }
 
 /*
Index: ufs/lfs/lfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_vnops.c,v
retrieving revision 1.126
diff -u -1 -0 -r1.126 lfs_vnops.c
--- ufs/lfs/lfs_vnops.c	16 Dec 2003 13:47:48 -0000	1.126
+++ ufs/lfs/lfs_vnops.c	19 Jan 2004 18:54:34 -0000
@@ -1095,21 +1095,21 @@
 				slept = 1;
 				break;
 			}
 		}
 		simple_lock(&fs->lfs_interlock);
 	}
 	simple_unlock(&fs->lfs_interlock);
 
 	vp = ip->i_devvp;
 	bp->b_dev = vp->v_rdev;
-	VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
+	VOP_STRATEGY(vp, bp);
 	return (0);
 }
 
 static void
 lfs_flush_dirops(struct lfs *fs)
 {
 	struct inode *ip, *nip;
 	struct vnode *vp;
 	extern int lfs_dostats;
 	struct segment *sp;
Index: ufs/ufs/ufs_bmap.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ufs/ufs_bmap.c,v
retrieving revision 1.26
diff -u -1 -0 -r1.26 ufs_bmap.c
--- ufs/ufs/ufs_bmap.c	10 Jan 2004 14:39:51 -0000	1.26
+++ ufs/ufs/ufs_bmap.c	19 Jan 2004 18:54:37 -0000
@@ -237,21 +237,21 @@
 		}
 #ifdef DIAGNOSTIC
 		else if (!daddr)
 			panic("ufs_bmaparry: indirect block not in cache");
 #endif
 		else {
 			trace(TR_BREADMISS, pack(vp, size), metalbn);
 			bp->b_blkno = blkptrtodb(ump, daddr);
 			bp->b_flags |= B_READ;
 			BIO_SETPRIO(bp, BPRIO_TIMECRITICAL);
-			VOP_STRATEGY(bp);
+			VOP_STRATEGY(vp, bp);
 			curproc->p_stats->p_ru.ru_inblock++;	/* XXX */
 			if ((error = biowait(bp)) != 0) {
 				brelse(bp);
 				return (error);
 			}
 		}
 		if (ip->i_ump->um_fstype == UFS1) {
 			daddr = (int32_t)ufs_rw32(
 			    ((int32_t *)bp->b_data)[xap->in_off],
 			    UFS_MPNEEDSWAP(mp));
Index: ufs/ufs/ufs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ufs/ufs_vnops.c,v
retrieving revision 1.109
diff -u -1 -0 -r1.109 ufs_vnops.c
--- ufs/ufs/ufs_vnops.c	8 Nov 2003 06:38:10 -0000	1.109
+++ ufs/ufs/ufs_vnops.c	19 Jan 2004 18:54:45 -0000
@@ -1724,21 +1724,21 @@
 		}
 		if ((long)bp->b_blkno == -1) /* no valid data */
 			clrbuf(bp);
 	}
 	if ((long)bp->b_blkno < 0) { /* block is not on disk */
 		biodone(bp);
 		return (0);
 	}
 	vp = ip->i_devvp;
 	bp->b_dev = vp->v_rdev;
-	VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
+	VOP_STRATEGY(vp, bp);
 	return (0);
 }
 
 /*
  * Print out the contents of an inode.
  */
 int
 ufs_print(void *v)
 {
 	struct vop_print_args /* {
Index: uvm/uvm_swap.c
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_swap.c,v
retrieving revision 1.83
diff -u -1 -0 -r1.83 uvm_swap.c
--- uvm/uvm_swap.c	10 Jan 2004 14:39:51 -0000	1.83
+++ uvm/uvm_swap.c	19 Jan 2004 18:54:55 -0000
@@ -1175,21 +1175,21 @@
 		if ((bp->b_flags & B_READ) == 0) {
 			vwakeup(bp);	/* kills one 'v_numoutput' on drum */
 			V_INCR_NUMOUTPUT(vp);	/* put it on swapdev */
 		}
 
 		/*
 		 * finally plug in swapdev vnode and start I/O
 		 */
 		bp->b_vp = vp;
 		splx(s);
-		VOP_STRATEGY(bp);
+		VOP_STRATEGY(vp, bp);
 		return;
 
 	case VREG:
 		/*
 		 * delegate to sw_reg_strategy function.
 		 */
 		sw_reg_strategy(sdp, bp, bn);
 		return;
 	}
 	/* NOTREACHED */
@@ -1369,21 +1369,21 @@
 		if (bp == NULL)
 			break;
 		sdp->swd_active++;
 
 		UVMHIST_LOG(pdhist,
 		    "sw_reg_start:  bp %p vp %p blkno %p cnt %lx",
 		    bp, bp->b_vp, bp->b_blkno, bp->b_bcount);
 		if ((bp->b_flags & B_READ) == 0)
 			V_INCR_NUMOUTPUT(bp->b_vp);
 
-		VOP_STRATEGY(bp);
+		VOP_STRATEGY(bp->b_vp, bp);
 	}
 	sdp->swd_flags &= ~SWF_BUSY;
 }
 
 /*
  * sw_reg_iodone: one of our i/o's has completed and needs post-i/o cleanup
  *
  * => note that we can recover the vndbuf struct by casting the buf ptr
  */
 static void
@@ -1757,21 +1757,21 @@
 		BIO_SETPRIO(bp, BPRIO_TIMECRITICAL);
 	}
 	UVMHIST_LOG(pdhist,
 	    "about to start io: data = %p blkno = 0x%x, bcount = %ld",
 	    bp->b_data, bp->b_blkno, bp->b_bcount, 0);
 
 	/*
 	 * now we start the I/O, and if async, return.
 	 */
 
-	VOP_STRATEGY(bp);
+	VOP_STRATEGY(swapdev_vp, bp);
 	if (async)
 		return 0;
 
 	/*
 	 * must be sync i/o.   wait for it to finish
 	 */
 
 	error = biowait(bp);
 
 	/*

--gBBFr7Ir9EOA20Yy--