diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2017-10-20 18:40:29 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2017-10-20 18:40:29 +0000 |
commit | b3d4ab6645064828aa342dd6cc652ed248c82ff2 (patch) | |
tree | 228349a7a33be32ae35dd0dbe1a6f23d61df29f3 /sys/vm/vnode_pager.c | |
parent | 9e9a610115acc70f5d3e4dd87ddc1733b0bd2fdb (diff) |
Take the vm object lock in read mode in vnode_generic_putpages().
Only upgrade it to write mode if we need to clear dirty bits of the
partially valid page after EOF.
Suggested and reviewed by: alc
Sponsored by: The FreeBSD Foundation
MFC after: 3 weeks
Notes
Notes:
svn path=/head/; revision=324807
Diffstat (limited to 'sys/vm/vnode_pager.c')
-rw-r--r-- | sys/vm/vnode_pager.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 83f10f75eace..e569503cc74d 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -1252,8 +1252,14 @@ vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount, * We do not under any circumstances truncate the valid bits, as * this will screw up bogus page replacement. */ - VM_OBJECT_WLOCK(object); + VM_OBJECT_RLOCK(object); if (maxsize + poffset > object->un_pager.vnp.vnp_size) { + if (!VM_OBJECT_TRYUPGRADE(object)) { + VM_OBJECT_RUNLOCK(object); + VM_OBJECT_WLOCK(object); + if (maxsize + poffset <= object->un_pager.vnp.vnp_size) + goto downgrade; + } if (object->un_pager.vnp.vnp_size > poffset) { maxsize = object->un_pager.vnp.vnp_size - poffset; ncount = btoc(maxsize); @@ -1278,6 +1284,8 @@ vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount, } for (i = ncount; i < count; i++) rtvals[i] = VM_PAGER_BAD; +downgrade: + VM_OBJECT_LOCK_DOWNGRADE(object); } auio.uio_iov = &aiov; @@ -1324,7 +1332,7 @@ start_write: */ MPASS(prev_offset < next_offset); - VM_OBJECT_WUNLOCK(object); + VM_OBJECT_RUNLOCK(object); aiov.iov_base = NULL; auio.uio_iovcnt = 1; auio.uio_offset = prev_offset; @@ -1340,7 +1348,7 @@ start_write: "zero-length write at %ju resid %zd\n", auio.uio_offset, auio.uio_resid); } - VM_OBJECT_WLOCK(object); + VM_OBJECT_RLOCK(object); break; } @@ -1358,7 +1366,7 @@ start_write: vn_printf(vp, "vnode_pager_putpages: residual I/O %zd " "at %ju\n", auio.uio_resid, (uintmax_t)ma[0]->pindex); - VM_OBJECT_WLOCK(object); + VM_OBJECT_RLOCK(object); if (error != 0 || auio.uio_resid != 0) break; } @@ -1372,7 +1380,7 @@ write_done: /* Unwritten pages in range, free bonus if the page is clean. */ for (; i < ncount; i++) rtvals[i] = ma[i]->dirty == 0 ? VM_PAGER_OK : VM_PAGER_ERROR; - VM_OBJECT_WUNLOCK(object); + VM_OBJECT_RUNLOCK(object); VM_CNT_ADD(v_vnodepgsout, i); VM_CNT_INC(v_vnodeout); return (rtvals[0]); |