Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Nov 2013 18:43:47 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r258353 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201311191843.rAJIhlSF026954@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Tue Nov 19 18:43:47 2013
New Revision: 258353
URL: http://svnweb.freebsd.org/changeset/base/258353

Log:
  zfs page_busy: fix the boundaries of the cleared range
  
  This is a fix for a regression introduced in r246293.
  
  vm_page_clear_dirty expects the range to have DEV_BSIZE aligned boundaries,
  otherwise it extends them.  Thus it can happen that the whole page is
  marked clean while actually having some small dirty region(s).
  This commit makes the range properly aligned and ensures that only
  the clean data is marked as such.
  
  It would interesting to evaluate how much benefit clearing with DEV_BSIZE
  granularity produces.  Perhaps instead we should clear the whole page
  when it is completely overwritten and don't bother clearing any bits
  if only a portion a page is written.
  
  Reported by:	George Hartzell <hartzell@alerce.com>,
  		Richard Todd <rmtodd@servalan.servalan.com>
  Tested by:	George Hartzell <hartzell@alerce.com>,
  Reviewed by:	kib
  MFC after:	5 days

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Tue Nov 19 18:35:38 2013	(r258352)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Tue Nov 19 18:43:47 2013	(r258353)
@@ -329,6 +329,20 @@ page_busy(vnode_t *vp, int64_t start, in
 {
 	vm_object_t obj;
 	vm_page_t pp;
+	int64_t end;
+
+	/*
+	 * At present vm_page_clear_dirty extends the cleared range to DEV_BSIZE
+	 * aligned boundaries, if the range is not aligned.  As a result a
+	 * DEV_BSIZE subrange with partially dirty data may get marked as clean.
+	 * It may happen that all DEV_BSIZE subranges are marked clean and thus
+	 * the whole page would be considred clean despite have some dirty data.
+	 * For this reason we should shrink the range to DEV_BSIZE aligned
+	 * boundaries before calling vm_page_clear_dirty.
+	 */
+	end = rounddown2(off + nbytes, DEV_BSIZE);
+	off = roundup2(off, DEV_BSIZE);
+	nbytes = end - off;
 
 	obj = vp->v_object;
 	zfs_vmobject_assert_wlocked(obj);
@@ -363,7 +377,8 @@ page_busy(vnode_t *vp, int64_t start, in
 			ASSERT3U(pp->valid, ==, VM_PAGE_BITS_ALL);
 			vm_object_pip_add(obj, 1);
 			pmap_remove_write(pp);
-			vm_page_clear_dirty(pp, off, nbytes);
+			if (nbytes != 0)
+				vm_page_clear_dirty(pp, off, nbytes);
 		}
 		break;
 	}



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