diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c index fc045dfbaf88..0972ec7400d6 100644 --- a/sys/fs/ext2fs/ext2_vnops.c +++ b/sys/fs/ext2fs/ext2_vnops.c @@ -97,7 +97,6 @@ static int ext2_chown(struct vnode *, uid_t, gid_t, struct ucred *, static vop_close_t ext2_close; static vop_create_t ext2_create; static vop_fsync_t ext2_fsync; -static vop_getpages_t ext2_getpages; static vop_getattr_t ext2_getattr; static vop_ioctl_t ext2_ioctl; static vop_link_t ext2_link; @@ -128,7 +127,7 @@ struct vop_vector ext2_vnodeops = { .vop_close = ext2_close, .vop_create = ext2_create, .vop_fsync = ext2_fsync, - .vop_getpages = ext2_getpages, + .vop_getpages = vnode_pager_local_getpages, .vop_getattr = ext2_getattr, .vop_inactive = ext2_inactive, .vop_ioctl = ext2_ioctl, @@ -2063,48 +2062,3 @@ ext2_write(struct vop_write_args *ap) } return (error); } - -/* - * get page routine - */ -static int -ext2_getpages(struct vop_getpages_args *ap) -{ - int i; - vm_page_t mreq; - int pcount; - - mreq = ap->a_m[ap->a_reqpage]; - - /* - * Since the caller has busied the requested page, that page's valid - * field will not be changed by other threads. - */ - vm_page_assert_xbusied(mreq); - - /* - * if ANY DEV_BSIZE blocks are valid on a large filesystem block, - * then the entire page is valid. Since the page may be mapped, - * user programs might reference data beyond the actual end of file - * occuring within the page. We have to zero that data. - */ - if (mreq->valid) { - VM_OBJECT_WLOCK(mreq->object); - if (mreq->valid != VM_PAGE_BITS_ALL) - vm_page_zero_invalid(mreq, TRUE); - pcount = round_page(ap->a_count) / PAGE_SIZE; - for (i = 0; i < pcount; i++) { - if (i != ap->a_reqpage) { - vm_page_lock(ap->a_m[i]); - vm_page_free(ap->a_m[i]); - vm_page_unlock(ap->a_m[i]); - } - } - VM_OBJECT_WUNLOCK(mreq->object); - return VM_PAGER_OK; - } - - return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, - ap->a_count, - ap->a_reqpage); -} diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index b6f255ef6a10..0dd4d1691c0d 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -104,7 +104,6 @@ extern int ffs_rawread(struct vnode *vp, struct uio *uio, int *workdone); #endif static vop_fsync_t ffs_fsync; static vop_lock1_t ffs_lock; -static vop_getpages_t ffs_getpages; static vop_read_t ffs_read; static vop_write_t ffs_write; static int ffs_extread(struct vnode *vp, struct uio *uio, int ioflag); @@ -124,7 +123,7 @@ static vop_vptofh_t ffs_vptofh; struct vop_vector ffs_vnodeops1 = { .vop_default = &ufs_vnodeops, .vop_fsync = ffs_fsync, - .vop_getpages = ffs_getpages, + .vop_getpages = vnode_pager_local_getpages, .vop_lock1 = ffs_lock, .vop_read = ffs_read, .vop_reallocblks = ffs_reallocblks, @@ -143,7 +142,7 @@ struct vop_vector ffs_fifoops1 = { struct vop_vector ffs_vnodeops2 = { .vop_default = &ufs_vnodeops, .vop_fsync = ffs_fsync, - .vop_getpages = ffs_getpages, + .vop_getpages = vnode_pager_local_getpages, .vop_lock1 = ffs_lock, .vop_read = ffs_read, .vop_reallocblks = ffs_reallocblks, @@ -846,53 +845,6 @@ ffs_write(ap) return (error); } -/* - * get page routine - */ -static int -ffs_getpages(ap) - struct vop_getpages_args *ap; -{ - int i; - vm_page_t mreq; - int pcount; - - mreq = ap->a_m[ap->a_reqpage]; - - /* - * Since the caller has busied the requested page, that page's valid - * field will not be changed by other threads. - */ - vm_page_assert_xbusied(mreq); - - /* - * if ANY DEV_BSIZE blocks are valid on a large filesystem block, - * then the entire page is valid. Since the page may be mapped, - * user programs might reference data beyond the actual end of file - * occuring within the page. We have to zero that data. - */ - if (mreq->valid) { - VM_OBJECT_WLOCK(mreq->object); - if (mreq->valid != VM_PAGE_BITS_ALL) - vm_page_zero_invalid(mreq, TRUE); - pcount = round_page(ap->a_count) / PAGE_SIZE; - for (i = 0; i < pcount; i++) { - if (i != ap->a_reqpage) { - vm_page_lock(ap->a_m[i]); - vm_page_free(ap->a_m[i]); - vm_page_unlock(ap->a_m[i]); - } - } - VM_OBJECT_WUNLOCK(mreq->object); - return VM_PAGER_OK; - } - - return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, - ap->a_count, - ap->a_reqpage); -} - - /* * Extended attribute area reading. */ diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 1b0dc7ebb160..817516df2ef3 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -664,6 +664,39 @@ vnode_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage) return rtval; } +/* + * The implementation of VOP_GETPAGES() for local filesystems, where + * partially valid pages can only occur at the end of file. + */ +int +vnode_pager_local_getpages(struct vop_getpages_args *ap) +{ + vm_page_t mreq; + + mreq = ap->a_m[ap->a_reqpage]; + + /* + * Since the caller has busied the requested page, that page's valid + * field will not be changed by other threads. + */ + vm_page_assert_xbusied(mreq); + + /* + * The requested page has valid blocks. Invalid part can only + * exist at the end of file, and the page is made fully valid + * by zeroing in vm_pager_getpages(). Free non-requested + * pages, since no i/o is done to read its content. + */ + if (mreq->valid != 0) { + vm_pager_free_nonreq(mreq->object, ap->a_m, ap->a_reqpage, + round_page(ap->a_count) / PAGE_SIZE); + return (VM_PAGER_OK); + } + + return (vnode_pager_generic_getpages(ap->a_vp, ap->a_m, + ap->a_count, ap->a_reqpage)); +} + /* * This is now called from local media FS's to operate against their * own vnodes if they fail to implement VOP_GETPAGES. diff --git a/sys/vm/vnode_pager.h b/sys/vm/vnode_pager.h index 02cf4c31453d..cf62557893c2 100644 --- a/sys/vm/vnode_pager.h +++ b/sys/vm/vnode_pager.h @@ -45,6 +45,8 @@ int vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *m, int count, boolean_t sync, int *rtvals); +struct vop_getpages_args; +int vnode_pager_local_getpages(struct vop_getpages_args *ap); void vnode_pager_release_writecount(vm_object_t object, vm_offset_t start, vm_offset_t end);