Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Oct 2017 18:40:29 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r324807 - head/sys/vm
Message-ID:  <201710201840.v9KIeT9F093717@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Fri Oct 20 18:40:29 2017
New Revision: 324807
URL: https://svnweb.freebsd.org/changeset/base/324807

Log:
  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

Modified:
  head/sys/vm/vnode_pager.c

Modified: head/sys/vm/vnode_pager.c
==============================================================================
--- head/sys/vm/vnode_pager.c	Fri Oct 20 15:29:28 2017	(r324806)
+++ head/sys/vm/vnode_pager.c	Fri Oct 20 18:40:29 2017	(r324807)
@@ -1252,8 +1252,14 @@ vnode_pager_generic_putpages(struct vnode *vp, vm_page
 	 * 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
 		}
 		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]);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201710201840.v9KIeT9F093717>