Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 2 Aug 2017 08:07:13 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r321910 - in stable/11/sys: fs/nfsclient fs/smbfs vm
Message-ID:  <201708020807.v7287DsY006353@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Aug  2 08:07:13 2017
New Revision: 321910
URL: https://svnweb.freebsd.org/changeset/base/321910

Log:
  MFC r321581:
  Mark pages after EOF as clean after pageout.

Modified:
  stable/11/sys/fs/nfsclient/nfs_clbio.c
  stable/11/sys/fs/smbfs/smbfs_io.c
  stable/11/sys/vm/vnode_pager.c
  stable/11/sys/vm/vnode_pager.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/fs/nfsclient/nfs_clbio.c
==============================================================================
--- stable/11/sys/fs/nfsclient/nfs_clbio.c	Wed Aug  2 08:03:40 2017	(r321909)
+++ stable/11/sys/fs/nfsclient/nfs_clbio.c	Wed Aug  2 08:07:13 2017	(r321910)
@@ -336,8 +336,10 @@ ncl_putpages(struct vop_putpages_args *ap)
 	    cred);
 	crfree(cred);
 
-	if (error == 0 || !nfs_keep_dirty_on_error)
-		vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
+	if (error == 0 || !nfs_keep_dirty_on_error) {
+		vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid,
+		    np->n_size - offset, npages * PAGE_SIZE);
+	}
 	return (rtvals[0]);
 }
 

Modified: stable/11/sys/fs/smbfs/smbfs_io.c
==============================================================================
--- stable/11/sys/fs/smbfs/smbfs_io.c	Wed Aug  2 08:03:40 2017	(r321909)
+++ stable/11/sys/fs/smbfs/smbfs_io.c	Wed Aug  2 08:07:13 2017	(r321910)
@@ -621,9 +621,11 @@ smbfs_putpages(ap)
 
 	relpbuf(bp, &smbfs_pbuf_freecnt);
 
-	if (!error)
-		vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
-	return rtvals[0];
+	if (error == 0) {
+		vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid,
+		    npages * PAGE_SIZE, npages * PAGE_SIZE);
+	}
+	return (rtvals[0]);
 #endif /* SMBFS_RWGENERIC */
 }
 

Modified: stable/11/sys/vm/vnode_pager.c
==============================================================================
--- stable/11/sys/vm/vnode_pager.c	Wed Aug  2 08:03:40 2017	(r321909)
+++ stable/11/sys/vm/vnode_pager.c	Wed Aug  2 08:07:13 2017	(r321910)
@@ -1276,13 +1276,24 @@ vnode_pager_putpages_ioflags(int pager_flags)
 	return (ioflags);
 }
 
+/*
+ * vnode_pager_undirty_pages().
+ *
+ * A helper to mark pages as clean after pageout that was possibly
+ * done with a short write.  The lpos argument specifies the page run
+ * length in bytes, and the written argument specifies how many bytes
+ * were actually written.  eof is the offset past the last valid byte
+ * in the vnode using the absolute file position of the first byte in
+ * the run as the base from which it is computed.
+ */
 void
-vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, int written)
+vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, int written, off_t eof,
+    int lpos)
 {
 	vm_object_t obj;
-	int i, pos;
+	int i, pos, pos_devb;
 
-	if (written == 0)
+	if (written == 0 && eof >= lpos)
 		return;
 	obj = ma[0]->object;
 	VM_OBJECT_WLOCK(obj);
@@ -1296,6 +1307,37 @@ vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, 
 			vm_page_clear_dirty(ma[i], 0, written & PAGE_MASK);
 		}
 	}
+	if (eof >= lpos) /* avoid truncation */
+		goto done;
+	for (pos = eof, i = OFF_TO_IDX(trunc_page(pos)); pos < lpos; i++) {
+		if (pos != trunc_page(pos)) {
+			/*
+			 * The page contains the last valid byte in
+			 * the vnode, mark the rest of the page as
+			 * clean, potentially making the whole page
+			 * clean.
+			 */
+			pos_devb = roundup2(pos & PAGE_MASK, DEV_BSIZE);
+			vm_page_clear_dirty(ma[i], pos_devb, PAGE_SIZE -
+			    pos_devb);
+
+			/*
+			 * If the page was cleaned, report the pageout
+			 * on it as successful.  msync() no longer
+			 * needs to write out the page, endlessly
+			 * creating write requests and dirty buffers.
+			 */
+			if (ma[i]->dirty == 0)
+				rtvals[i] = VM_PAGER_OK;
+
+			pos = round_page(pos);
+		} else {
+			/* vm_pageout_flush() clears dirty */
+			rtvals[i] = VM_PAGER_BAD;
+			pos += PAGE_SIZE;
+		}
+	}
+done:
 	VM_OBJECT_WUNLOCK(obj);
 }
 

Modified: stable/11/sys/vm/vnode_pager.h
==============================================================================
--- stable/11/sys/vm/vnode_pager.h	Wed Aug  2 08:03:40 2017	(r321909)
+++ stable/11/sys/vm/vnode_pager.h	Wed Aug  2 08:07:13 2017	(r321910)
@@ -50,7 +50,8 @@ int vnode_pager_local_getpages_async(struct vop_getpag
 int vnode_pager_putpages_ioflags(int pager_flags);
 void vnode_pager_release_writecount(vm_object_t object, vm_offset_t start,
     vm_offset_t end);
-void vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, int written);
+void vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, int written,
+    off_t eof, int lpos);
 void vnode_pager_update_writecount(vm_object_t object, vm_offset_t start,
     vm_offset_t end);
 



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