diff options
author | alc <alc@FreeBSD.org> | 2014-09-13 18:26:13 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2014-09-13 18:26:13 +0000 |
commit | e169525bb8bf99d439947a14544f261295aa4731 (patch) | |
tree | c6fecd2d028f499d428c002526db85f000d42981 /sys/fs | |
parent | 5630fccbd418933428669ff406733a2f798f63b4 (diff) | |
download | FreeBSD-src-e169525bb8bf99d439947a14544f261295aa4731.zip FreeBSD-src-e169525bb8bf99d439947a14544f261295aa4731.tar.gz |
We don't need an exclusive object lock on the expected execution path
through {ext2,ffs}_getpages().
Reviewed by: kib, pfg
MFC after: 6 weeks
Sponsored by: EMC / Isilon Storage Division
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/ext2fs/ext2_vnops.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c index e68bc64..fc045df 100644 --- a/sys/fs/ext2fs/ext2_vnops.c +++ b/sys/fs/ext2fs/ext2_vnops.c @@ -2074,19 +2074,25 @@ ext2_getpages(struct vop_getpages_args *ap) vm_page_t mreq; int pcount; - pcount = round_page(ap->a_count) / PAGE_SIZE; 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. */ - VM_OBJECT_WLOCK(mreq->object); 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]); @@ -2097,7 +2103,6 @@ ext2_getpages(struct vop_getpages_args *ap) VM_OBJECT_WUNLOCK(mreq->object); return VM_PAGER_OK; } - VM_OBJECT_WUNLOCK(mreq->object); return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count, |