summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/fs/cd9660/cd9660_vnops.c2
-rw-r--r--sys/fs/hpfs/hpfs_vnops.c2
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c2
-rw-r--r--sys/fs/specfs/spec_vnops.c41
-rw-r--r--sys/fs/udf/udf_vnops.c2
-rw-r--r--sys/isofs/cd9660/cd9660_vnops.c2
-rw-r--r--sys/kern/vfs_bio.c15
-rw-r--r--sys/kern/vfs_default.c25
-rw-r--r--sys/kern/vnode_if.src9
-rw-r--r--sys/ufs/ufs/ufs_vnops.c2
-rw-r--r--sys/vm/vm_swap.c2
11 files changed, 92 insertions, 12 deletions
diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c
index 1fae0f7..0b892e6 100644
--- a/sys/fs/cd9660/cd9660_vnops.c
+++ b/sys/fs/cd9660/cd9660_vnops.c
@@ -731,7 +731,7 @@ cd9660_strategy(ap)
}
vp = ip->i_devvp;
bp->b_dev = vp->v_rdev;
- VOP_STRATEGY(vp, bp);
+ VOP_SPECSTRATEGY(vp, bp);
return (0);
}
diff --git a/sys/fs/hpfs/hpfs_vnops.c b/sys/fs/hpfs/hpfs_vnops.c
index c3ad1e7..7d10096 100644
--- a/sys/fs/hpfs/hpfs_vnops.c
+++ b/sys/fs/hpfs/hpfs_vnops.c
@@ -706,7 +706,7 @@ hpfs_strategy(ap)
return (0);
}
bp->b_dev = hp->h_devvp->v_rdev;
- VOP_STRATEGY(hp->h_devvp, bp);
+ VOP_SPECSTRATEGY(hp->h_devvp, bp);
return (0);
}
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index 06a677f..a326929 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -1820,7 +1820,7 @@ msdosfs_strategy(ap)
*/
vp = dep->de_devvp;
bp->b_dev = vp->v_rdev;
- VOP_STRATEGY(vp, bp);
+ VOP_SPECSTRATEGY(vp, bp);
return (0);
}
diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c
index 61b4732..e0274bf 100644
--- a/sys/fs/specfs/spec_vnops.c
+++ b/sys/fs/specfs/spec_vnops.c
@@ -56,7 +56,6 @@
#include <vm/vm_page.h>
#include <vm/vm_pager.h>
-
static int spec_advlock(struct vop_advlock_args *);
static int spec_close(struct vop_close_args *);
static int spec_freeblks(struct vop_freeblks_args *);
@@ -69,6 +68,8 @@ static int spec_poll(struct vop_poll_args *);
static int spec_print(struct vop_print_args *);
static int spec_read(struct vop_read_args *);
static int spec_strategy(struct vop_strategy_args *);
+static int spec_xstrategy(struct vop_strategy_args *);
+static int spec_specstrategy(struct vop_specstrategy_args *);
static int spec_write(struct vop_write_args *);
vop_t **spec_vnodeop_p;
@@ -104,6 +105,7 @@ static struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
{ &vop_rename_desc, (vop_t *) vop_panic },
{ &vop_rmdir_desc, (vop_t *) vop_panic },
{ &vop_setattr_desc, (vop_t *) vop_ebadf },
+ { &vop_specstrategy_desc, (vop_t *) spec_specstrategy },
{ &vop_strategy_desc, (vop_t *) spec_strategy },
{ &vop_symlink_desc, (vop_t *) vop_panic },
{ &vop_unlock_desc, (vop_t *) vop_nounlock },
@@ -522,7 +524,7 @@ SYSCTL_INT(_debug, OID_AUTO, doslowdown, CTLFLAG_RW, &doslowdown, 0, "");
* Just call the device strategy routine
*/
static int
-spec_strategy(ap)
+spec_xstrategy(ap)
struct vop_strategy_args /* {
struct vnode *a_vp;
struct buf *a_bp;
@@ -609,6 +611,41 @@ spec_strategy(ap)
return (0);
}
+/*
+ * Decoy strategy routine. We should always come in via the specstrategy
+ * method, but in case some code has botched it, we have a strategy as
+ * well. We will deal with the request anyway and first time around we
+ * print some debugging useful information.
+ */
+
+static int
+spec_strategy(ap)
+ struct vop_strategy_args /* {
+ struct vnode *a_vp;
+ struct buf *a_bp;
+ } */ *ap;
+{
+ static int once;
+
+ if (!once) {
+ vprint("\nVOP_STRATEGY on VCHR\n", ap->a_vp);
+ backtrace();
+ once++;
+ }
+ return spec_xstrategy(ap);
+}
+
+static int
+spec_specstrategy(ap)
+ struct vop_specstrategy_args /* {
+ struct vnode *a_vp;
+ struct buf *a_bp;
+ } */ *ap;
+{
+
+ return spec_xstrategy((void *)ap);
+}
+
static int
spec_freeblks(ap)
struct vop_freeblks_args /* {
diff --git a/sys/fs/udf/udf_vnops.c b/sys/fs/udf/udf_vnops.c
index 0670275..8d9be57 100644
--- a/sys/fs/udf/udf_vnops.c
+++ b/sys/fs/udf/udf_vnops.c
@@ -828,7 +828,7 @@ udf_strategy(struct vop_strategy_args *a)
}
vp = node->i_devvp;
bp->b_dev = vp->v_rdev;
- VOP_STRATEGY(vp, bp);
+ VOP_SPECSTRATEGY(vp, bp);
return (0);
}
diff --git a/sys/isofs/cd9660/cd9660_vnops.c b/sys/isofs/cd9660/cd9660_vnops.c
index 1fae0f7..0b892e6 100644
--- a/sys/isofs/cd9660/cd9660_vnops.c
+++ b/sys/isofs/cd9660/cd9660_vnops.c
@@ -731,7 +731,7 @@ cd9660_strategy(ap)
}
vp = ip->i_devvp;
bp->b_dev = vp->v_rdev;
- VOP_STRATEGY(vp, bp);
+ VOP_SPECSTRATEGY(vp, bp);
return (0);
}
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 65fcb33..784a5c0 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -701,7 +701,10 @@ breadn(struct vnode * vp, daddr_t blkno, int size,
if (bp->b_rcred == NOCRED && cred != NOCRED)
bp->b_rcred = crhold(cred);
vfs_busy_pages(bp, 0);
- VOP_STRATEGY(vp, bp);
+ if (vp->v_type == VCHR)
+ VOP_SPECSTRATEGY(vp, bp);
+ else
+ VOP_STRATEGY(vp, bp);
++readwait;
}
@@ -721,7 +724,10 @@ breadn(struct vnode * vp, daddr_t blkno, int size,
rabp->b_rcred = crhold(cred);
vfs_busy_pages(rabp, 0);
BUF_KERNPROC(rabp);
- VOP_STRATEGY(vp, rabp);
+ if (vp->v_type == VCHR)
+ VOP_SPECSTRATEGY(vp, bp);
+ else
+ VOP_STRATEGY(vp, bp);
} else {
brelse(rabp);
}
@@ -855,7 +861,10 @@ bwrite(struct buf * bp)
splx(s);
if (oldflags & B_ASYNC)
BUF_KERNPROC(bp);
- VOP_STRATEGY(bp->b_vp, bp);
+ if (bp->b_vp->v_type == VCHR)
+ VOP_SPECSTRATEGY(bp->b_vp, bp);
+ else
+ VOP_STRATEGY(bp->b_vp, bp);
if ((oldflags & B_ASYNC) == 0) {
int rtval = bufwait(bp);
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index 85b8af9..f629b19 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -66,6 +66,7 @@
static int vop_nolookup(struct vop_lookup_args *);
static int vop_nostrategy(struct vop_strategy_args *);
+static int vop_nospecstrategy(struct vop_specstrategy_args *);
/*
* This vnode table stores what we want to do if the filesystem doesn't
@@ -98,6 +99,7 @@ static struct vnodeopv_entry_desc default_vnodeop_entries[] = {
{ &vop_putpages_desc, (vop_t *) vop_stdputpages },
{ &vop_readlink_desc, (vop_t *) vop_einval },
{ &vop_revoke_desc, (vop_t *) vop_revoke },
+ { &vop_specstrategy_desc, (vop_t *) vop_nospecstrategy },
{ &vop_strategy_desc, (vop_t *) vop_nostrategy },
{ &vop_unlock_desc, (vop_t *) vop_stdunlock },
{ NULL, NULL }
@@ -221,6 +223,29 @@ vop_nostrategy (struct vop_strategy_args *ap)
}
/*
+ * vop_nospecstrategy:
+ *
+ * This shouldn't happen. VOP_SPECSTRATEGY should always have a VCHR
+ * argument vnode, and thos have a method for specstrategy over in
+ * specfs, so we only ever get here if somebody botched it.
+ * Pass the call to VOP_STRATEGY() and get on with life.
+ * The first time we print some info useful for debugging.
+ */
+
+static int
+vop_nospecstrategy (struct vop_specstrategy_args *ap)
+{
+ static int once;
+
+ if (!once) {
+ vprint("\nVOP_SPECSTRATEGY on non-VCHR\n", ap->a_vp);
+ backtrace();
+ once++;
+ }
+ return VOP_STRATEGY(ap->a_vp, ap->a_bp);
+}
+
+/*
* vop_stdpathconf:
*
* Standard implementation of POSIX pathconf, to get information about limits
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
index 4fce819..f62d0ac 100644
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -400,6 +400,15 @@ vop_strategy {
};
#
+# specstrategy vp L L L
+#! specstrategy pre vop_strategy_pre
+#
+vop_specstrategy {
+ IN struct vnode *vp;
+ IN struct buf *bp;
+};
+
+#
#% getwritemount vp = = =
#
vop_getwritemount {
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index a4adc9a..af65b36 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -1968,7 +1968,7 @@ ufs_strategy(ap)
}
vp = ip->i_devvp;
bp->b_dev = vp->v_rdev;
- VOP_STRATEGY(vp, bp);
+ VOP_SPECSTRATEGY(vp, bp);
return (0);
}
diff --git a/sys/vm/vm_swap.c b/sys/vm/vm_swap.c
index 7edb969..f586d5d 100644
--- a/sys/vm/vm_swap.c
+++ b/sys/vm/vm_swap.c
@@ -164,7 +164,7 @@ swapdev_strategy(ap)
}
bp->b_vp = sp->sw_vp;
splx(s);
- VOP_STRATEGY(bp->b_vp, bp);
+ VOP_SPECSTRATEGY(bp->b_vp, bp);
return 0;
}
OpenPOWER on IntegriCloud