summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--sys/vm/swap_pager.c21
-rw-r--r--sys/vm/vm_swap.c51
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);
}
OpenPOWER on IntegriCloud