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
This commit is contained in:
parent
94ce1a985e
commit
6e0007fa82
@ -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.
|
||||
|
@ -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,8 +151,24 @@ 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
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user