From ce75f2c365a32572982d8e77ee0405f5b2bd7d8d Mon Sep 17 00:00:00 2001 From: Mike Smith Date: Thu, 26 Feb 1998 06:39:59 +0000 Subject: [PATCH] In the author's words: These diffs implement the first stage of a VOP_{GET|PUT}PAGES pushdown for local media FS's. See ffs_putpages in /sys/ufs/ufs/ufs_readwrite.c for implementation details for generic *_{get|put}pages for local media FS's. Support is trivial to add for any FS that formerly relied on the default behaviour of the vnode_pager in in EOPNOTSUPP cases (just copy the ffs_getpages() code for the FS in question's *_{get|put}pages). Obviously, it would be better if each local media FS implemented a more optimal method, instead of calling an exported interface from the /sys/vm/vnode_pager.c, but this is a necessary first step in getting the FS's to a point where they can be supplied with better implementations on a case-by-case basis. Obviously, the cd9660_putpages() can be rather trivial (since it is a read-only FS type 8-)). A slight (temporary) modification is made to print a diagnostic message in the case where the underlying filesystem attempts to engage in the previous behaviour. Failure is likely to be ungraceful. Submitted by: terry@freebsd.org (Terry Lambert) --- sys/ufs/ffs/ffs_vnops.c | 4 +- sys/ufs/ufs/ufs_readwrite.c | 16 +++++++- sys/vm/vnode_pager.c | 78 ++++++++++++++++++++++++------------- sys/vm/vnode_pager.h | 12 +++++- 4 files changed, 80 insertions(+), 30 deletions(-) diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 522f0891134..0210d61458e 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95 - * $Id: ffs_vnops.c,v 1.41 1998/02/04 22:33:33 eivind Exp $ + * $Id: ffs_vnops.c,v 1.42 1998/02/06 12:14:16 eivind Exp $ */ #include @@ -62,6 +62,7 @@ static int ffs_fsync __P((struct vop_fsync_args *)); static int ffs_getpages __P((struct vop_getpages_args *)); +static int ffs_putpages __P((struct vop_putpages_args *)); static int ffs_read __P((struct vop_read_args *)); static int ffs_write __P((struct vop_write_args *)); @@ -71,6 +72,7 @@ static struct vnodeopv_entry_desc ffs_vnodeop_entries[] = { { &vop_default_desc, (vop_t *) ufs_vnoperate }, { &vop_fsync_desc, (vop_t *) ffs_fsync }, { &vop_getpages_desc, (vop_t *) ffs_getpages }, + { &vop_putpages_desc, (vop_t *) ffs_putpages }, { &vop_read_desc, (vop_t *) ffs_read }, { &vop_reallocblks_desc, (vop_t *) ffs_reallocblks }, { &vop_write_desc, (vop_t *) ffs_write }, diff --git a/sys/ufs/ufs/ufs_readwrite.c b/sys/ufs/ufs/ufs_readwrite.c index 3996692396b..19f72804314 100644 --- a/sys/ufs/ufs/ufs_readwrite.c +++ b/sys/ufs/ufs/ufs_readwrite.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ufs_readwrite.c 8.11 (Berkeley) 5/8/95 - * $Id: ufs_readwrite.c,v 1.41 1998/01/30 11:34:05 phk Exp $ + * $Id: ufs_readwrite.c,v 1.42 1998/02/05 03:32:33 dyson Exp $ */ #define BLKSIZE(a, b, c) blksize(a, b, c) @@ -539,3 +539,17 @@ ffs_getpages(ap) return (rtval); } + +/* + * put page routine + * + * XXX By default, wimp out... note that a_offset is ignored (and always + * XXX has been). + */ +int +ffs_putpages(ap) + struct vop_putpages_args *ap; +{ + return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count, + ap->a_sync, ap->a_rtvals); +} diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 98b57b04bf0..ae934c1c35c 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91 - * $Id: vnode_pager.c,v 1.85 1998/02/23 08:22:48 dyson Exp $ + * $Id: vnode_pager.c,v 1.86 1998/02/25 03:55:53 dyson Exp $ */ /* @@ -88,11 +88,6 @@ struct pagerops vnodepagerops = { NULL }; -static int vnode_pager_leaf_getpages __P((vm_object_t object, vm_page_t *m, - int count, int reqpage)); -static int vnode_pager_leaf_putpages __P((vm_object_t object, vm_page_t *m, - int count, boolean_t sync, - int *rtvals)); /* * Allocate (or lookup) pager for a vnode. @@ -519,6 +514,14 @@ vnode_pager_input_old(object, m) * generic vnode pager input routine */ +/* + * EOPNOTSUPP is no longer legal. For local media VFS's that do not + * implement their own VOP_GETPAGES, their VOP_GETPAGES should call to + * vnode_pager_generic_getpages() to implement the previous behaviour. + * + * All other FS's should use the bypass to get to the local media + * backing vp's VOP_GETPAGES. + */ static int vnode_pager_getpages(object, m, count, reqpage) vm_object_t object; @@ -530,31 +533,43 @@ vnode_pager_getpages(object, m, count, reqpage) struct vnode *vp; vp = object->handle; + /* + * XXX temporary diagnostic message to help track stale FS code, + * Returning EOPNOTSUPP from here may make things unhappy. + */ rtval = VOP_GETPAGES(vp, m, count*PAGE_SIZE, reqpage, 0); if (rtval == EOPNOTSUPP) - return vnode_pager_leaf_getpages(object, m, count, reqpage); - else - return rtval; + printf("vnode_pager: *** WARNING *** stale FS code in system.\n"); + return rtval; } -static int -vnode_pager_leaf_getpages(object, m, count, reqpage) - vm_object_t object; + +/* + * This is now called from local media FS's to operate against their + * own vnodes if they fail to implement VOP_GETPAGES. + */ +int +vnode_pager_generic_getpages(vp, m, bytecount, reqpage) + struct vnode *vp; vm_page_t *m; - int count; + int bytecount; int reqpage; { + vm_object_t object; vm_offset_t kva; off_t foff; int i, size, bsize, first, firstaddr; - struct vnode *dp, *vp; + struct vnode *dp; int runpg; int runend; struct buf *bp; int s; + int count; int error = 0; - vp = object->handle; + object = vp->v_object; + count = bytecount / PAGE_SIZE; + if (vp->v_mount == NULL) return VM_PAGER_BAD; @@ -770,6 +785,14 @@ vnode_pager_leaf_getpages(object, m, count, reqpage) return (error ? VM_PAGER_ERROR : VM_PAGER_OK); } +/* + * EOPNOTSUPP is no longer legal. For local media VFS's that do not + * implement their own VOP_PUTPAGES, their VOP_PUTPAGES should call to + * vnode_pager_generic_putpages() to implement the previous behaviour. + * + * All other FS's should use the bypass to get to the local media + * backing vp's VOP_PUTPAGES. + */ static int vnode_pager_putpages(object, m, count, sync, rtvals) vm_object_t object; @@ -782,34 +805,35 @@ vnode_pager_putpages(object, m, count, sync, rtvals) struct vnode *vp; vp = object->handle; - rtval = VOP_PUTPAGES(vp, m, count*PAGE_SIZE, sync, rtvals, 0); - if (rtval == EOPNOTSUPP) - return vnode_pager_leaf_putpages(object, m, count, sync, rtvals); - else - return rtval; + return VOP_PUTPAGES(vp, m, count*PAGE_SIZE, sync, rtvals, 0); } + /* - * generic vnode pager output routine + * This is now called from local media FS's to operate against their + * own vnodes if they fail to implement VOP_GETPAGES. */ -static int -vnode_pager_leaf_putpages(object, m, count, sync, rtvals) - vm_object_t object; +int +vnode_pager_generic_putpages(vp, m, bytecount, sync, rtvals) + struct vnode *vp; vm_page_t *m; - int count; + int bytecount; boolean_t sync; int *rtvals; { int i; + vm_object_t object; + int count; - struct vnode *vp; int maxsize, ncount; vm_ooffset_t poffset; struct uio auio; struct iovec aiov; int error; - vp = object->handle;; + object = vp->v_object; + count = bytecount / PAGE_SIZE; + for (i = 0; i < count; i++) rtvals[i] = VM_PAGER_AGAIN; diff --git a/sys/vm/vnode_pager.h b/sys/vm/vnode_pager.h index c7a0c9be34b..4402e14723c 100644 --- a/sys/vm/vnode_pager.h +++ b/sys/vm/vnode_pager.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vnode_pager.h 8.1 (Berkeley) 6/11/93 - * $Id$ + * $Id: vnode_pager.h,v 1.10 1997/02/22 09:48:43 peter Exp $ */ #ifndef _VNODE_PAGER_ @@ -46,6 +46,16 @@ vm_object_t vnode_pager_alloc __P((void *, vm_size_t, vm_prot_t, vm_ooffset_t)); void vnode_pager_freepage __P((vm_page_t m)); struct vnode *vnode_pager_lock __P((vm_object_t)); + +/* + * XXX Generic routines; currently called by badly written FS code; these + * XXX should go away soon. + */ +int vnode_pager_generic_getpages __P((struct vnode *vp, vm_page_t *m, + int count, int reqpage)); +int vnode_pager_generic_putpages __P((struct vnode *vp, vm_page_t *m, + int count, boolean_t sync, + int *rtvals)); #endif #endif /* _VNODE_PAGER_ */