diff options
author | Poul-Henning Kamp <phk@FreeBSD.org> | 2003-08-30 11:33:25 +0000 |
---|---|---|
committer | Poul-Henning Kamp <phk@FreeBSD.org> | 2003-08-30 11:33:25 +0000 |
commit | 59efee01a3b7de1ba27f9859691a00b9e2a86d44 (patch) | |
tree | ab0847c0e07de20eb6c148f7b066d3db913492e3 /sys/vm/swap_pager.c | |
parent | 4b03903a4637a751878b6919fd37755fcfc29d1e (diff) | |
download | src-59efee01a3b7de1ba27f9859691a00b9e2a86d44.tar.gz src-59efee01a3b7de1ba27f9859691a00b9e2a86d44.zip |
Continue the objectification of the swapdev backends:
Remove the vnode and dev_t fields and replace them with a void *.
Introduce separate strategy functions for devices and regular (NFS)
vnodes.
For devices we don't need the vnode v_numoutput stuff.
Add a generic swaponsomething() function to add a swapdevice and
split the remainder of swaponvp() into swaponvp() and swapondev()
which calls this backend.
Notes
Notes:
svn path=/head/; revision=119575
Diffstat (limited to 'sys/vm/swap_pager.c')
-rw-r--r-- | sys/vm/swap_pager.c | 165 |
1 files changed, 106 insertions, 59 deletions
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 11f40bc1f4ff..844d6544e41a 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -148,11 +148,10 @@ typedef void sw_strategy_t(struct buf *bp, struct swdevt *sw); * Swap device table */ struct swdevt { - dev_t sw_dev; int sw_flags; int sw_nblks; int sw_used; - struct vnode *sw_vp; + void *sw_id; swblk_t sw_first; swblk_t sw_end; struct blist *sw_blist; @@ -257,7 +256,8 @@ SYSCTL_INT(_vm, OID_AUTO, dmmax, static void swp_sizecheck(void); static void swp_pager_sync_iodone(struct buf *bp); static void swp_pager_async_iodone(struct buf *bp); -static int swaponvp(struct thread *, struct vnode *, dev_t , u_long); +static int swapondev(struct thread *, struct vnode *); +static int swaponvp(struct thread *, struct vnode *, u_long); /* * Swap bitmap functions @@ -2002,18 +2002,14 @@ swp_pager_meta_ctl(vm_object_t object, vm_pindex_t pindex, int flags) static void swapdev_strategy(struct buf *bp, struct swdevt *sp) { - int s, sz; - struct vnode *vp; - - sz = howmany(bp->b_bcount, PAGE_SIZE); + int s; + struct vnode *vp, *vp2; - bp->b_dev = sp->sw_dev; - /* - * Convert from PAGE_SIZE'd to DEV_BSIZE'd chunks for the actual I/O - */ + bp->b_dev = NODEV; bp->b_blkno = ctodb(bp->b_blkno - sp->sw_first); - vhold(sp->sw_vp); + vp2 = sp->sw_id; + vhold(vp2); s = splvm(); if (bp->b_iocmd == BIO_WRITE) { vp = bp->b_vp; @@ -2026,16 +2022,26 @@ swapdev_strategy(struct buf *bp, struct swdevt *sp) } VI_UNLOCK(vp); } - VI_LOCK(sp->sw_vp); - sp->sw_vp->v_numoutput++; - VI_UNLOCK(sp->sw_vp); + VI_LOCK(vp2); + vp2->v_numoutput++; + VI_UNLOCK(vp2); } - bp->b_vp = sp->sw_vp; + bp->b_vp = vp2; splx(s); - if (bp->b_vp->v_type == VCHR) - VOP_SPECSTRATEGY(bp->b_vp, bp); - else - VOP_STRATEGY(bp->b_vp, bp); + VOP_STRATEGY(vp2, bp); + return; +} + +static void +swapdev_devstrategy(struct buf *bp, struct swdevt *sp) +{ + struct vnode *vp; + + vp = sp->sw_id; + bp->b_dev = vp->v_rdev; + bp->b_blkno = ctodb(bp->b_blkno - sp->sw_first); + + VOP_SPECSTRATEGY(vp, bp); return; } @@ -2089,7 +2095,7 @@ swapon(struct thread *td, struct swapon_args *uap) vp = nd.ni_vp; if (vn_isdisk(vp, &error)) - error = swaponvp(td, vp, vp->v_rdev, 0); + error = swapondev(td, vp); else if (vp->v_type == VREG && (vp->v_mount->mnt_vfc->vfc_flags & VFCF_NETWORK) != 0 && (error = VOP_GETATTR(vp, &attr, td->td_ucred, td)) == 0) { @@ -2097,7 +2103,7 @@ swapon(struct thread *td, struct swapon_args *uap) * Allow direct swapping to NFS regular files in the same * way that nfs_mountroot() sets up diskless swapping. */ - error = swaponvp(td, vp, NODEV, attr.va_size / DEV_BSIZE); + error = swaponvp(td, vp, attr.va_size / DEV_BSIZE); } if (error) @@ -2110,19 +2116,15 @@ done2: return (error); } -static int -swaponvp(struct thread *td, struct vnode *vp, dev_t dev, u_long nblks) +static void +swaponsomething(struct vnode *vp, u_long nblks, sw_strategy_t *strategy) { struct swdevt *sp; swblk_t dvbase; - int error; u_long mblocks; - off_t mediasize; dvbase = 0; TAILQ_FOREACH(sp, &swtailq, sw_list) { - if (sp->sw_vp == vp) - return (EBUSY); if (sp->sw_end >= dvbase) { /* * We put one uncovered page between the devices @@ -2133,31 +2135,6 @@ swaponvp(struct thread *td, struct vnode *vp, dev_t dev, u_long nblks) } } - (void) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); -#ifdef MAC - error = mac_check_system_swapon(td->td_ucred, vp); - if (error == 0) -#endif - error = VOP_OPEN(vp, FREAD | FWRITE, td->td_ucred, td, -1); - (void) VOP_UNLOCK(vp, 0, td); - if (error) - return (error); - - if (nblks == 0) { - error = VOP_IOCTL(vp, DIOCGMEDIASIZE, (caddr_t)&mediasize, - FREAD, td->td_ucred, td); - if (error == 0) - nblks = mediasize / DEV_BSIZE; - } - /* - * XXX: We should also check that the sectorsize makes sense - * XXX: it should be a power of two, no larger than the page size. - */ - if (nblks == 0) { - (void) VOP_CLOSE(vp, FREAD | FWRITE, td->td_ucred, td); - return (ENXIO); - } - /* * If we go beyond this, we get overflows in the radix * tree bitmap code. @@ -2178,14 +2155,13 @@ swaponvp(struct thread *td, struct vnode *vp, dev_t dev, u_long nblks) nblks = dbtoc(nblks); sp = malloc(sizeof *sp, M_VMPGDATA, M_WAITOK | M_ZERO); - sp->sw_vp = vp; - sp->sw_dev = dev; + sp->sw_id = vp; sp->sw_flags = 0; sp->sw_nblks = nblks; sp->sw_used = 0; sp->sw_first = dvbase; sp->sw_end = dvbase + nblks; - sp->sw_strategy = swapdev_strategy; + sp->sw_strategy = strategy; sp->sw_blist = blist_create(nblks); /* @@ -2198,7 +2174,73 @@ swaponvp(struct thread *td, struct vnode *vp, dev_t dev, u_long nblks) nswapdev++; swap_pager_avail += nblks; swap_pager_full = 0; +} + + +static int +swapondev(struct thread *td, struct vnode *vp) +{ + struct swdevt *sp; + int error; + off_t mediasize; + u_long nblks; + TAILQ_FOREACH(sp, &swtailq, sw_list) + if (sp->sw_id == vp) + return (EBUSY); + + (void) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); +#ifdef MAC + error = mac_check_system_swapon(td->td_ucred, vp); + if (error == 0) +#endif + error = VOP_OPEN(vp, FREAD | FWRITE, td->td_ucred, td, -1); + (void) VOP_UNLOCK(vp, 0, td); + if (error) + return (error); + + error = VOP_IOCTL(vp, DIOCGMEDIASIZE, (caddr_t)&mediasize, + FREAD, td->td_ucred, td); + if (error == 0) + nblks = mediasize / DEV_BSIZE; + else { + (void) VOP_CLOSE(vp, FREAD | FWRITE, td->td_ucred, td); + return (ENXIO); + } + + /* + * XXX: We should also check that the sectorsize makes sense + * XXX: it should be a power of two, no larger than the page size. + */ + + swaponsomething(vp, nblks, swapdev_devstrategy); + return (0); +} + + +static int +swaponvp(struct thread *td, struct vnode *vp, u_long nblks) +{ + struct swdevt *sp; + int error; + + if (nblks == 0) + return (ENXIO); + TAILQ_FOREACH(sp, &swtailq, sw_list) + if (sp->sw_id == vp) + return (EBUSY); + + (void) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); +#ifdef MAC + error = mac_check_system_swapon(td->td_ucred, vp); + if (error == 0) +#endif + error = VOP_OPEN(vp, FREAD | FWRITE, td->td_ucred, td, -1); + (void) VOP_UNLOCK(vp, 0, td); + if (error) + return (error); + + swaponsomething(vp, nblks, swapdev_strategy); return (0); } @@ -2244,7 +2286,7 @@ swapoff(struct thread *td, struct swapoff_args *uap) vp = nd.ni_vp; TAILQ_FOREACH(sp, &swtailq, sw_list) { - if (sp->sw_vp == vp) + if (sp->sw_id == vp) goto found; } error = EINVAL; @@ -2291,7 +2333,7 @@ found: VOP_CLOSE(vp, FREAD | FWRITE, td->td_ucred, td); vrele(vp); - sp->sw_vp = NULL; + sp->sw_id = NULL; TAILQ_REMOVE(&swtailq, sp, sw_list); if (swdevhd == sp) swdevhd = NULL; @@ -2327,6 +2369,7 @@ sysctl_vm_swap_info(SYSCTL_HANDLER_ARGS) int error, n; struct xswdev xs; struct swdevt *sp; + struct vnode *vp; if (arg2 != 1) /* name length */ return (EINVAL); @@ -2335,7 +2378,11 @@ sysctl_vm_swap_info(SYSCTL_HANDLER_ARGS) TAILQ_FOREACH(sp, &swtailq, sw_list) { if (n == *name) { xs.xsw_version = XSWDEV_VERSION; - xs.xsw_dev = dev2udev(sp->sw_dev); + vp = sp->sw_id; + if (vp->v_rdev != NULL) + xs.xsw_dev = dev2udev(vp->v_rdev); + else + xs.xsw_dev = NOUDEV; xs.xsw_flags = sp->sw_flags; xs.xsw_nblks = sp->sw_nblks; xs.xsw_used = sp->sw_used; |