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 | |
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')
-rw-r--r-- | sys/vm/swap_pager.c | 21 | ||||
-rw-r--r-- | sys/vm/vm_swap.c | 51 |
2 files changed, 50 insertions, 22 deletions
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 0805795..82b2040 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -120,7 +120,7 @@ static struct swblock **swhash; static int swhash_mask; static int swap_async_max = 4; /* maximum in-progress async I/O's */ -static struct vnode *swapdev_vp; /* XXX: This is not quite a real vnode */ +extern struct vnode *swapdev_vp; /* from vm_swap.c */ SYSCTL_INT(_vm, OID_AUTO, swap_async_max, CTLFLAG_RW, &swap_async_max, 0, "Maximum running async swap ops"); @@ -328,11 +328,6 @@ swap_pager_swap_init() bzero(swhash, sizeof(struct swblock *) * n); swhash_mask = n - 1; - - n = getnewvnode(VT_NON, NULL, spec_vnodeop_p, &swapdev_vp); - if (n) - panic("Cannot get vnode for swapdev"); - swapdev_vp->v_type = VBLK; } /* @@ -1136,11 +1131,11 @@ swap_pager_getpages(object, m, count, reqpage) * The other pages in our m[] array are also released on completion, * so we cannot assume they are valid anymore either. * - * NOTE: b_blkno is destroyed by the call to swstrategy() + * NOTE: b_blkno is destroyed by the call to VOP_STRATEGY */ BUF_KERNPROC(bp); - swstrategy(bp); + VOP_STRATEGY(bp->b_vp, bp); /* * wait for the page we want to complete. PG_SWAPINPROG is always @@ -1193,7 +1188,7 @@ swap_pager_getpages(object, m, count, reqpage) * We support both OBJT_DEFAULT and OBJT_SWAP objects. DEFAULT objects * are automatically converted to SWAP objects. * - * In a low memory situation we may block in swstrategy(), but the new + * In a low memory situation we may block in VOP_STRATEGY(), but the new * vm_page reservation system coupled with properly written VFS devices * should ensure that no low-memory deadlock occurs. This is an area * which needs work. @@ -1387,13 +1382,13 @@ swap_pager_putpages(object, m, count, sync, rtvals) /* * asynchronous * - * NOTE: b_blkno is destroyed by the call to swstrategy() + * NOTE: b_blkno is destroyed by the call to VOP_STRATEGY */ if (sync == FALSE) { bp->b_iodone = swp_pager_async_iodone; BUF_KERNPROC(bp); - swstrategy(bp); + VOP_STRATEGY(bp->b_vp, bp); for (j = 0; j < n; ++j) rtvals[i+j] = VM_PAGER_PEND; @@ -1403,11 +1398,11 @@ swap_pager_putpages(object, m, count, sync, rtvals) /* * synchronous * - * NOTE: b_blkno is destroyed by the call to swstrategy() + * NOTE: b_blkno is destroyed by the call to VOP_STRATEGY */ bp->b_iodone = swp_pager_sync_iodone; - swstrategy(bp); + VOP_STRATEGY(bp->b_vp, bp); /* * Wait for the sync I/O to complete, then update rtvals. 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); } |