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)
This commit is contained in:
parent
4c1d902bb2
commit
d15b55c554
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user