summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2014-09-15 12:28:29 +0000
committerkib <kib@FreeBSD.org>2014-09-15 12:28:29 +0000
commitebd8a253bb50d17048c8bbdcc4d20b61c1fa75b5 (patch)
tree1fa12b673a05ff33b8b047e0e2780130b56d0e15
parent0dba5e79e39c9f67a8f141a37d5c6b8fcaff6b46 (diff)
downloadFreeBSD-src-ebd8a253bb50d17048c8bbdcc4d20b61c1fa75b5.zip
FreeBSD-src-ebd8a253bb50d17048c8bbdcc4d20b61c1fa75b5.tar.gz
Provide the unique implementation for the VOP_GETPAGES() method used
by ffs and ext2fs. Remove duplicated call to vm_page_zero_invalid(), done by VOP and by vm_pager_getpages(). Use vm_pager_free_nonreq(). Reviewed by: alc (previous version) Sponsored by: The FreeBSD Foundation MFC after: 6 weeks (after r271596)
-rw-r--r--sys/fs/ext2fs/ext2_vnops.c48
-rw-r--r--sys/ufs/ffs/ffs_vnops.c52
-rw-r--r--sys/vm/vnode_pager.c33
-rw-r--r--sys/vm/vnode_pager.h2
4 files changed, 38 insertions, 97 deletions
diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c
index fc045df..0972ec7 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 b6f255e..0dd4d16 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,
@@ -847,53 +846,6 @@ ffs_write(ap)
}
/*
- * 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.
*/
static int
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 1b0dc7e..817516d 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -665,6 +665,39 @@ vnode_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
}
/*
+ * 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 02cf4c3..cf62557 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);
OpenPOWER on IntegriCloud