diff options
author | peter <peter@FreeBSD.org> | 1999-12-28 07:30:55 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1999-12-28 07:30:55 +0000 |
commit | 38a9421a1e400014ef261a0d4de1fe80e5817d0c (patch) | |
tree | ab78c1f23a1962395cd710e3da06ceac2717dd5c /sys/vm/vm_swap.c | |
parent | 425c15d62c595f2d72c762761a0a2f2d77117e5a (diff) | |
download | FreeBSD-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.c | 51 |
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); } |