Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 13 Sep 2014 18:26:13 +0000 (UTC)
From:      Alan Cox <alc@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r271540 - in head/sys: fs/ext2fs ufs/ffs
Message-ID:  <201409131826.s8DIQDD6068262@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: alc
Date: Sat Sep 13 18:26:13 2014
New Revision: 271540
URL: http://svnweb.freebsd.org/changeset/base/271540

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

Modified:
  head/sys/fs/ext2fs/ext2_vnops.c
  head/sys/ufs/ffs/ffs_vnops.c

Modified: head/sys/fs/ext2fs/ext2_vnops.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_vnops.c	Sat Sep 13 18:24:54 2014	(r271539)
+++ head/sys/fs/ext2fs/ext2_vnops.c	Sat Sep 13 18:26:13 2014	(r271540)
@@ -2074,19 +2074,25 @@ ext2_getpages(struct vop_getpages_args *
 	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 *
 		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,

Modified: head/sys/ufs/ffs/ffs_vnops.c
==============================================================================
--- head/sys/ufs/ffs/ffs_vnops.c	Sat Sep 13 18:24:54 2014	(r271539)
+++ head/sys/ufs/ffs/ffs_vnops.c	Sat Sep 13 18:26:13 2014	(r271540)
@@ -857,19 +857,25 @@ ffs_getpages(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]);
@@ -880,7 +886,6 @@ ffs_getpages(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,



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