summaryrefslogtreecommitdiffstats
path: root/sys/vm/vm_swap.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1999-12-28 07:30:55 +0000
committerpeter <peter@FreeBSD.org>1999-12-28 07:30:55 +0000
commit38a9421a1e400014ef261a0d4de1fe80e5817d0c (patch)
treeab78c1f23a1962395cd710e3da06ceac2717dd5c /sys/vm/vm_swap.c
parent425c15d62c595f2d72c762761a0a2f2d77117e5a (diff)
downloadFreeBSD-src-38a9421a1e400014ef261a0d4de1fe80e5817d0c.zip
FreeBSD-src-38a9421a1e400014ef261a0d4de1fe80e5817d0c.tar.gz
Fix the swap backed vn case - this was broken by my rev 1.128 to
swap_pager.c and related commits. Essentially swap_pager.c is backed out to before the changes, but swapdev_vp is converted into a real vnode with just VOP_STRATEGY(). It no longer abuses specfs vnops and no longer needs a dev_t and /dev/drum (or /dev/swapdev) for the intermediate layer. This essentially restores the vnode interface as the interface to the bottom of the swap pager, and vm_swap.c provides a clean vnode interface. This will need to be revisited when we swap to files (vnodes) - which is the other reason for keeping the vnode interface between the swap pager and the swap devices. OK'ed by: dillon
Diffstat (limited to 'sys/vm/vm_swap.c')
-rw-r--r--sys/vm/vm_swap.c51
1 files changed, 42 insertions, 9 deletions
diff --git a/sys/vm/vm_swap.c b/sys/vm/vm_swap.c
index 9140c1f..23bddad 100644
--- a/sys/vm/vm_swap.c
+++ b/sys/vm/vm_swap.c
@@ -68,36 +68,45 @@ static int nswap; /* first block after the interleaved devs */
static int nswdev = NSWAPDEV;
int vm_swap_size;
+static int swapdev_strategy __P((struct vop_strategy_args *ap));
+struct vnode *swapdev_vp;
+
/*
- * swstrategy:
+ * swapdev_strategy:
*
- * Perform swap strategy interleave device selection
+ * VOP_STRATEGY() for swapdev_vp.
+ * Perform swap strategy interleave device selection.
*
* The bp is expected to be locked and *not* B_DONE on call.
*/
-void
-swstrategy(bp)
- register struct buf *bp;
+static int
+swapdev_strategy(ap)
+ struct vop_strategy_args /* {
+ struct vnode *a_vp;
+ struct buf *a_bp;
+ } */ *ap;
{
int s, sz, off, seg, index;
register struct swdevt *sp;
struct vnode *vp;
+ struct buf *bp;
+ bp = ap->a_bp;
sz = howmany(bp->b_bcount, PAGE_SIZE);
+
/*
* Convert interleaved swap into per-device swap. Note that
* the block size is left in PAGE_SIZE'd chunks (for the newswap)
* here.
*/
-
if (nswdev > 1) {
off = bp->b_blkno % dmmax;
if (off + sz > dmmax) {
bp->b_error = EINVAL;
bp->b_flags |= B_ERROR;
biodone(bp);
- return;
+ return 0;
}
seg = bp->b_blkno / dmmax;
index = seg % nswdev;
@@ -111,14 +120,14 @@ swstrategy(bp)
bp->b_error = EINVAL;
bp->b_flags |= B_ERROR;
biodone(bp);
- return;
+ return 0;
}
bp->b_dev = sp->sw_device;
if (sp->sw_vp == NULL) {
bp->b_error = ENODEV;
bp->b_flags |= B_ERROR;
biodone(bp);
- return;
+ return 0;
}
/*
@@ -142,9 +151,25 @@ swstrategy(bp)
pbreassignbuf(bp, sp->sw_vp);
splx(s);
VOP_STRATEGY(bp->b_vp, bp);
+ return 0;
}
/*
+ * Create a special vnode op vector for swapdev_vp - we only use
+ * VOP_STRATEGY(), everything else returns an error.
+ */
+vop_t **swapdev_vnodeop_p;
+static struct vnodeopv_entry_desc swapdev_vnodeop_entries[] = {
+ { &vop_default_desc, (vop_t *) vop_defaultop },
+ { &vop_strategy_desc, (vop_t *) swapdev_strategy },
+ { NULL, NULL }
+};
+static struct vnodeopv_desc swapdev_vnodeop_opv_desc =
+ { &swapdev_vnodeop_p, swapdev_vnodeop_entries };
+
+VNODEOP_SET(swapdev_vnodeop_opv_desc);
+
+/*
* System call swapon(name) enables swapping on device name,
* which must be in the swdevsw. Return EBUSY
* if already swapping on this device.
@@ -186,6 +211,14 @@ swapon(p, uap)
if (error)
vrele(vp);
+ if (!swapdev_vp) {
+ error = getnewvnode(VT_NON, NULL, swapdev_vnodeop_p,
+ &swapdev_vp);
+ if (error)
+ panic("Cannot get vnode for swapdev");
+ swapdev_vp->v_type = VNON; /* Untyped */
+ }
+
return (error);
}
OpenPOWER on IntegriCloud