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
This commit is contained in:
parent
9e9a610115
commit
b3d4ab6645
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=324807
@ -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 @@ vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount,
|
||||
*/
|
||||
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 @@ vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount,
|
||||
"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 @@ vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount,
|
||||
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 @@ vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount,
|
||||
/* 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]);
|
||||
|
Loading…
Reference in New Issue
Block a user