svn commit: r280189 - in head/sys: fs/nfsclient vm
Gleb Smirnoff
glebius at FreeBSD.org
Tue Mar 17 19:19:21 UTC 2015
Author: glebius
Date: Tue Mar 17 19:19:19 2015
New Revision: 280189
URL: https://svnweb.freebsd.org/changeset/base/280189
Log:
o Enhance vm_pager_free_nonreq() function:
- Allow to call the function with vm object lock held.
- Allow to specify reqpage that doesn't match any page in the region,
meaning freeing all pages.
o Utilize the new function in couple more places in vnode pager.
Reviewed by: alc, kib
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
Modified:
head/sys/fs/nfsclient/nfs_clbio.c
head/sys/vm/vm_pager.c
head/sys/vm/vm_pager.h
head/sys/vm/vnode_pager.c
Modified: head/sys/fs/nfsclient/nfs_clbio.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clbio.c Tue Mar 17 19:16:51 2015 (r280188)
+++ head/sys/fs/nfsclient/nfs_clbio.c Tue Mar 17 19:19:19 2015 (r280189)
@@ -140,7 +140,8 @@ ncl_getpages(struct vop_getpages_args *a
* can only occur at the file EOF.
*/
if (pages[ap->a_reqpage]->valid != 0) {
- vm_pager_free_nonreq(object, pages, ap->a_reqpage, npages);
+ vm_pager_free_nonreq(object, pages, ap->a_reqpage, npages,
+ FALSE);
return (VM_PAGER_OK);
}
@@ -172,7 +173,8 @@ ncl_getpages(struct vop_getpages_args *a
if (error && (uio.uio_resid == count)) {
ncl_printf("nfs_getpages: error %d\n", error);
- vm_pager_free_nonreq(object, pages, ap->a_reqpage, npages);
+ vm_pager_free_nonreq(object, pages, ap->a_reqpage, npages,
+ FALSE);
return (VM_PAGER_ERROR);
}
Modified: head/sys/vm/vm_pager.c
==============================================================================
--- head/sys/vm/vm_pager.c Tue Mar 17 19:16:51 2015 (r280188)
+++ head/sys/vm/vm_pager.c Tue Mar 17 19:19:19 2015 (r280189)
@@ -283,29 +283,35 @@ vm_pager_object_lookup(struct pagerlst *
}
/*
- * Free the non-requested pages from the given array.
+ * Free the non-requested pages from the given array. To remove all pages,
+ * caller should provide out of range reqpage number.
*/
void
vm_pager_free_nonreq(vm_object_t object, vm_page_t ma[], int reqpage,
- int npages)
+ int npages, boolean_t object_locked)
{
+ enum { UNLOCKED, CALLER_LOCKED, INTERNALLY_LOCKED } locked;
int i;
- boolean_t object_locked;
- VM_OBJECT_ASSERT_UNLOCKED(object);
- object_locked = FALSE;
+ if (object_locked) {
+ VM_OBJECT_ASSERT_WLOCKED(object);
+ locked = CALLER_LOCKED;
+ } else {
+ VM_OBJECT_ASSERT_UNLOCKED(object);
+ locked = UNLOCKED;
+ }
for (i = 0; i < npages; ++i) {
if (i != reqpage) {
- if (!object_locked) {
+ if (locked == UNLOCKED) {
VM_OBJECT_WLOCK(object);
- object_locked = TRUE;
+ locked = INTERNALLY_LOCKED;
}
vm_page_lock(ma[i]);
vm_page_free(ma[i]);
vm_page_unlock(ma[i]);
}
}
- if (object_locked)
+ if (locked == INTERNALLY_LOCKED)
VM_OBJECT_WUNLOCK(object);
}
Modified: head/sys/vm/vm_pager.h
==============================================================================
--- head/sys/vm/vm_pager.h Tue Mar 17 19:16:51 2015 (r280188)
+++ head/sys/vm/vm_pager.h Tue Mar 17 19:19:19 2015 (r280189)
@@ -113,7 +113,7 @@ static __inline boolean_t vm_pager_has_p
void vm_pager_init(void);
vm_object_t vm_pager_object_lookup(struct pagerlst *, void *);
void vm_pager_free_nonreq(vm_object_t object, vm_page_t ma[], int reqpage,
- int npages);
+ int npages, boolean_t object_locked);
/*
* vm_page_get_pages:
Modified: head/sys/vm/vnode_pager.c
==============================================================================
--- head/sys/vm/vnode_pager.c Tue Mar 17 19:16:51 2015 (r280188)
+++ head/sys/vm/vnode_pager.c Tue Mar 17 19:19:19 2015 (r280189)
@@ -732,7 +732,7 @@ vnode_pager_local_getpages0(struct vnode
*/
if (mreq->valid != 0) {
vm_pager_free_nonreq(mreq->object, m, reqpage,
- round_page(bytecount) / PAGE_SIZE);
+ round_page(bytecount) / PAGE_SIZE, FALSE);
if (iodone != NULL)
iodone(arg, m, reqpage, 0);
return (VM_PAGER_OK);
@@ -806,7 +806,7 @@ vnode_pager_generic_getpages(struct vnod
return (error);
} else if (error != 0) {
relpbuf(bp, freecnt);
- vm_pager_free_nonreq(object, m, reqpage, count);
+ vm_pager_free_nonreq(object, m, reqpage, count, FALSE);
return (VM_PAGER_ERROR);
/*
@@ -817,7 +817,7 @@ vnode_pager_generic_getpages(struct vnod
} else if ((PAGE_SIZE / bsize) > 1 &&
(vp->v_mount->mnt_stat.f_type != nfs_mount_type)) {
relpbuf(bp, freecnt);
- vm_pager_free_nonreq(object, m, reqpage, count);
+ vm_pager_free_nonreq(object, m, reqpage, count, FALSE);
PCPU_INC(cnt.v_vnodein);
PCPU_INC(cnt.v_vnodepgsin);
return vnode_pager_input_smlfs(object, m[reqpage]);
@@ -836,7 +836,7 @@ vnode_pager_generic_getpages(struct vnod
*/
if (m[reqpage]->valid == VM_PAGE_BITS_ALL) {
relpbuf(bp, freecnt);
- vm_pager_free_nonreq(object, m, reqpage, count);
+ vm_pager_free_nonreq(object, m, reqpage, count, FALSE);
return (VM_PAGER_OK);
} else if (reqblock == -1) {
relpbuf(bp, freecnt);
@@ -845,12 +845,7 @@ vnode_pager_generic_getpages(struct vnod
("vnode_pager_generic_getpages: page %p is dirty", m));
VM_OBJECT_WLOCK(object);
m[reqpage]->valid = VM_PAGE_BITS_ALL;
- for (i = 0; i < count; i++)
- if (i != reqpage) {
- vm_page_lock(m[i]);
- vm_page_free(m[i]);
- vm_page_unlock(m[i]);
- }
+ vm_pager_free_nonreq(object, m, reqpage, count, TRUE);
VM_OBJECT_WUNLOCK(object);
return (VM_PAGER_OK);
} else if (m[reqpage]->valid != 0) {
@@ -871,14 +866,9 @@ vnode_pager_generic_getpages(struct vnod
if (vnode_pager_addr(vp, IDX_TO_OFF(m[i]->pindex), &firstaddr,
&runpg) != 0) {
relpbuf(bp, freecnt);
- VM_OBJECT_WLOCK(object);
- for (; i < count; i++)
- if (i != reqpage) {
- vm_page_lock(m[i]);
- vm_page_free(m[i]);
- vm_page_unlock(m[i]);
- }
- VM_OBJECT_WUNLOCK(object);
+ /* The requested page may be out of range. */
+ vm_pager_free_nonreq(object, m + i, reqpage - i,
+ count - i, FALSE);
return (VM_PAGER_ERROR);
}
if (firstaddr == -1) {
More information about the svn-src-all
mailing list