Module Name:    src
Committed By:   yamt
Date:           Wed Aug  1 22:34:15 UTC 2012

Modified Files:
        src/sys/miscfs/genfs [yamt-pagecache]: genfs_io.c
        src/sys/uvm [yamt-pagecache]: uvm_object.h uvm_page_array.c
            uvm_page_array.h uvm_page_status.c uvm_pager.c uvm_vnode.c

Log Message:
- fix integrity sync.
  putpages for integrity sync (fsync, msync with MS_SYNC, etc) should not
  skip pages being written back by other threads.

- adapt to radix tree tag api changes.


To generate a diff of this commit:
cvs rdiff -u -r1.53.2.15 -r1.53.2.16 src/sys/miscfs/genfs/genfs_io.c
cvs rdiff -u -r1.31.2.3 -r1.31.2.4 src/sys/uvm/uvm_object.h
cvs rdiff -u -r1.1.2.5 -r1.1.2.6 src/sys/uvm/uvm_page_array.c \
    src/sys/uvm/uvm_page_array.h
cvs rdiff -u -r1.1.2.7 -r1.1.2.8 src/sys/uvm/uvm_page_status.c
cvs rdiff -u -r1.107.2.3 -r1.107.2.4 src/sys/uvm/uvm_pager.c
cvs rdiff -u -r1.97.2.6 -r1.97.2.7 src/sys/uvm/uvm_vnode.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/miscfs/genfs/genfs_io.c
diff -u src/sys/miscfs/genfs/genfs_io.c:1.53.2.15 src/sys/miscfs/genfs/genfs_io.c:1.53.2.16
--- src/sys/miscfs/genfs/genfs_io.c:1.53.2.15	Wed Aug  1 21:13:45 2012
+++ src/sys/miscfs/genfs/genfs_io.c	Wed Aug  1 22:34:15 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: genfs_io.c,v 1.53.2.15 2012/08/01 21:13:45 yamt Exp $	*/
+/*	$NetBSD: genfs_io.c,v 1.53.2.16 2012/08/01 22:34:15 yamt Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.53.2.15 2012/08/01 21:13:45 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.53.2.16 2012/08/01 22:34:15 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -834,8 +834,7 @@ genfs_do_putpages(struct vnode *vp, off_
 	int error;
 	struct vm_page *pgs[maxpages], *pg;
 	struct uvm_page_array a;
-	bool wasclean, needs_clean, yld;
-	bool async = (origflags & PGO_SYNCIO) == 0;
+	bool wasclean, needs_clean;
 	bool pagedaemon = curlwp == uvm.pagedaemon_lwp;
 	struct lwp * const l = curlwp ? curlwp : &lwp0;
 	int flags;
@@ -844,6 +843,8 @@ genfs_do_putpages(struct vnode *vp, off_
 	bool has_trans;
 	bool tryclean;		/* try to pull off from the syncer's list */
 	bool onworklst;
+	const bool integrity_sync =
+	    (origflags & (PGO_LAZY|PGO_SYNCIO)) == PGO_SYNCIO;
 	const bool dirtyonly = (origflags & (PGO_DEACTIVATE|PGO_FREE)) == 0;
 
 	UVMHIST_FUNC("genfs_putpages"); UVMHIST_CALLED(ubchist);
@@ -941,45 +942,59 @@ retry:
 	for (;;) {
 		bool protected;
 
+		/*
+		 * if we are asked to sync for integrity, we should wait on
+		 * pages being written back by another threads as well.
+		 */
+
 		pg = uvm_page_array_fill_and_peek(&a, uobj, nextoff, 0,
-		    dirtyonly ? UVM_PAGE_ARRAY_FILL_DIRTYONLY : 0);
+		    dirtyonly ? (UVM_PAGE_ARRAY_FILL_DIRTY |
+		    (integrity_sync ? UVM_PAGE_ARRAY_FILL_WRITEBACK : 0)) : 0);
 		if (pg == NULL) {
 			break;
 		}
 
-		/*
-		 * if the current page is not interesting, move on to the next.
-		 */
-
 		KASSERT(pg->uobject == uobj);
 		KASSERT((pg->flags & (PG_RELEASED|PG_PAGEOUT)) == 0 ||
 		    (pg->flags & (PG_BUSY)) != 0);
 		KASSERT(pg->offset >= startoff);
 		KASSERT(pg->offset >= nextoff);
 		KASSERT(!dirtyonly ||
-		    uvm_pagegetdirty(pg) != UVM_PAGE_STATUS_CLEAN);
+		    uvm_pagegetdirty(pg) != UVM_PAGE_STATUS_CLEAN ||
+		    radix_tree_get_tag(&uobj->uo_pages,
+			pg->offset >> PAGE_SHIFT, UVM_PAGE_WRITEBACK_TAG));
 		if (pg->offset >= endoff) {
 			break;
 		}
-		if (pg->flags & (PG_RELEASED|PG_PAGEOUT)) {
-			KASSERT((pg->flags & PG_BUSY) != 0);
-			wasclean = false;
-			nextoff = pg->offset + PAGE_SIZE;
-			uvm_page_array_advance(&a);
+
+		/*
+		 * a preempt point.
+		 */
+
+		if ((l->l_cpu->ci_schedstate.spc_flags & SPCF_SHOULDYIELD)
+		    != 0) {
+			nextoff = pg->offset; /* visit this page again */
+			mutex_exit(slock);
+			preempt();
+			/*
+			 * as we dropped the object lock, our cached pages can
+			 * be stale.
+			 */
+			uvm_page_array_clear(&a);
+			mutex_enter(slock);
 			continue;
 		}
 
 		/*
-		 * if the current page needs to be cleaned and it's busy,
-		 * wait for it to become unbusy.
+		 * if the current page is busy, wait for it to become unbusy.
 		 */
 
-		yld = (l->l_cpu->ci_schedstate.spc_flags &
-		    SPCF_SHOULDYIELD) && !pagedaemon;
-		if (pg->flags & PG_BUSY || yld) {
+		if ((pg->flags & PG_BUSY) != 0) {
 			UVMHIST_LOG(ubchist, "busy %p", pg,0,0,0);
-			if (flags & PGO_BUSYFAIL && pg->flags & PG_BUSY) {
-				UVMHIST_LOG(ubchist, "busyfail %p", pg, 0,0,0);
+			if ((pg->flags & (PG_RELEASED|PG_PAGEOUT)) != 0
+			    && (flags & PGO_BUSYFAIL) != 0) {
+				UVMHIST_LOG(ubchist, "busyfail %p", pg,
+				    0,0,0);
 				error = EDEADLK;
 				if (busypg != NULL)
 					*busypg = pg;
@@ -992,15 +1007,19 @@ retry:
 				 */
 				break;
 			}
-			nextoff = pg->offset; /* visit this page again */
-			if ((pg->flags & PG_BUSY) != 0) {
-				pg->flags |= PG_WANTED;
-				UVM_UNLOCK_AND_WAIT(pg, slock, 0, "genput", 0);
-			} else {
-				KASSERT(yld);
-				mutex_exit(slock);
-				preempt();
+			/*
+			 * don't bother to wait on other's activities
+			 * unless we are asked to sync for integrity.
+			 */
+			if (!integrity_sync) {
+				wasclean = false;
+				nextoff = pg->offset + PAGE_SIZE;
+				uvm_page_array_advance(&a);
+				continue;
 			}
+			nextoff = pg->offset; /* visit this page again */
+			pg->flags |= PG_WANTED;
+			UVM_UNLOCK_AND_WAIT(pg, slock, 0, "genput", 0);
 			/*
 			 * as we dropped the object lock, our cached pages can
 			 * be stale.
@@ -1160,6 +1179,15 @@ retry:
 			    pgs[i-1]->offset + PAGE_SIZE == tpg->offset);
 			KASSERT(!needs_clean || uvm_pagegetdirty(pgs[i]) !=
 			    UVM_PAGE_STATUS_DIRTY);
+			if (needs_clean) {
+				/*
+				 * mark pages as WRITEBACK so that concurrent
+				 * fsync can find and wait for our activities.
+				 */
+				radix_tree_set_tag(&uobj->uo_pages,
+				    pgs[i]->offset >> PAGE_SHIFT,
+				    UVM_PAGE_WRITEBACK_TAG);
+			}
 			if (tpg->offset < startoff || tpg->offset >= endoff)
 				continue;
 			if (flags & PGO_DEACTIVATE && tpg->wire_count == 0) {
@@ -1254,11 +1282,11 @@ skip_scan:
 #endif /* !defined(DEBUG) */
 
 	/*
-	 * if we found or started any i/o and we're doing sync i/o,
+	 * if we found or started any i/o and we're asked to sync for integrity,
 	 * wait for all writes to finish.
 	 */
 
-	if (!wasclean && !async) {
+	if (!wasclean && integrity_sync) {
 		while (vp->v_numoutput != 0)
 			cv_wait(&vp->v_cv, slock);
 	}
@@ -1379,6 +1407,10 @@ genfs_do_io(struct vnode *vp, off_t off,
 	KASSERT(bytes != 0);
 
 	if (iowrite) {
+		/*
+		 * why += 2?
+		 * 1 for biodone, 1 for uvm_aio_aiodone.
+		 */
 		mutex_enter(vp->v_interlock);
 		vp->v_numoutput += 2;
 		mutex_exit(vp->v_interlock);

Index: src/sys/uvm/uvm_object.h
diff -u src/sys/uvm/uvm_object.h:1.31.2.3 src/sys/uvm/uvm_object.h:1.31.2.4
--- src/sys/uvm/uvm_object.h:1.31.2.3	Tue Apr 17 00:09:00 2012
+++ src/sys/uvm/uvm_object.h	Wed Aug  1 22:34:14 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_object.h,v 1.31.2.3 2012/04/17 00:09:00 yamt Exp $	*/
+/*	$NetBSD: uvm_object.h,v 1.31.2.4 2012/08/01 22:34:14 yamt Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -60,10 +60,11 @@ struct uvm_object {
 };
 
 /*
- * uo_pages
+ * tags for uo_pages
  */
 
-#define	UVM_PAGE_DIRTY_TAG	0	/* might be dirty (!PG_CLEAN) */
+#define	UVM_PAGE_DIRTY_TAG	1	/* might be dirty (!PG_CLEAN) */
+#define	UVM_PAGE_WRITEBACK_TAG	2	/* being written back */
 
 /*
  * UVM_OBJ_KERN is a 'special' uo_refs value which indicates that the

Index: src/sys/uvm/uvm_page_array.c
diff -u src/sys/uvm/uvm_page_array.c:1.1.2.5 src/sys/uvm/uvm_page_array.c:1.1.2.6
--- src/sys/uvm/uvm_page_array.c:1.1.2.5	Wed Apr 18 13:40:44 2012
+++ src/sys/uvm/uvm_page_array.c	Wed Aug  1 22:34:14 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_page_array.c,v 1.1.2.5 2012/04/18 13:40:44 yamt Exp $	*/
+/*	$NetBSD: uvm_page_array.c,v 1.1.2.6 2012/08/01 22:34:14 yamt Exp $	*/
 
 /*-
  * Copyright (c)2011 YAMAMOTO Takashi,
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_page_array.c,v 1.1.2.5 2012/04/18 13:40:44 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_page_array.c,v 1.1.2.6 2012/08/01 22:34:14 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -142,12 +142,17 @@ uvm_page_array_fill(struct uvm_page_arra
 	KASSERT(mutex_owned(uobj->vmobjlock));
 #endif
 	KASSERT(uvm_page_array_peek(ar) == NULL);
-	if ((flags & UVM_PAGE_ARRAY_FILL_DIRTYONLY) != 0) {
+	if ((flags & UVM_PAGE_ARRAY_FILL_DIRTY) != 0) {
+		unsigned int tagmask = UVM_PAGE_DIRTY_TAG;
+
+		if ((flags & UVM_PAGE_ARRAY_FILL_WRITEBACK) != 0) {
+			tagmask |= UVM_PAGE_WRITEBACK_TAG;
+		}
 		npages =
 		    (backward ? radix_tree_gang_lookup_tagged_node_reverse :
 		    radix_tree_gang_lookup_tagged_node)(
 		    &uobj->uo_pages, off >> PAGE_SHIFT, (void **)ar->ar_pages,
-		    maxpages, dense, UVM_PAGE_DIRTY_TAG);
+		    maxpages, dense, tagmask);
 	} else {
 		npages =
 		    (backward ? radix_tree_gang_lookup_node_reverse :
Index: src/sys/uvm/uvm_page_array.h
diff -u src/sys/uvm/uvm_page_array.h:1.1.2.5 src/sys/uvm/uvm_page_array.h:1.1.2.6
--- src/sys/uvm/uvm_page_array.h:1.1.2.5	Wed Apr 18 13:39:28 2012
+++ src/sys/uvm/uvm_page_array.h	Wed Aug  1 22:34:14 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_page_array.h,v 1.1.2.5 2012/04/18 13:39:28 yamt Exp $	*/
+/*	$NetBSD: uvm_page_array.h,v 1.1.2.6 2012/08/01 22:34:14 yamt Exp $	*/
 
 /*-
  * Copyright (c)2011 YAMAMOTO Takashi,
@@ -71,8 +71,9 @@ struct vm_page *uvm_page_array_fill_and_
 /*
  * flags for uvm_page_array_fill and uvm_page_array_fill_and_peek
  */
-#define	UVM_PAGE_ARRAY_FILL_DIRTYONLY	1	/* skip known-clean pages */
-#define	UVM_PAGE_ARRAY_FILL_DENSE	2	/* stop on a hole */
-#define	UVM_PAGE_ARRAY_FILL_BACKWARD	4	/* descend order */
+#define	UVM_PAGE_ARRAY_FILL_DIRTY	1	/* dirty pages */
+#define	UVM_PAGE_ARRAY_FILL_WRITEBACK	2	/* dirty or written-back */
+#define	UVM_PAGE_ARRAY_FILL_DENSE	4	/* stop on a hole */
+#define	UVM_PAGE_ARRAY_FILL_BACKWARD	8	/* descend order */
 
 #endif /* defined(_UVM_UVM_ARRAY_H_) */

Index: src/sys/uvm/uvm_page_status.c
diff -u src/sys/uvm/uvm_page_status.c:1.1.2.7 src/sys/uvm/uvm_page_status.c:1.1.2.8
--- src/sys/uvm/uvm_page_status.c:1.1.2.7	Tue Jan 24 02:11:33 2012
+++ src/sys/uvm/uvm_page_status.c	Wed Aug  1 22:34:14 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_page_status.c,v 1.1.2.7 2012/01/24 02:11:33 yamt Exp $	*/
+/*	$NetBSD: uvm_page_status.c,v 1.1.2.8 2012/08/01 22:34:14 yamt Exp $	*/
 
 /*-
  * Copyright (c)2011 YAMAMOTO Takashi,
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_page_status.c,v 1.1.2.7 2012/01/24 02:11:33 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_page_status.c,v 1.1.2.8 2012/08/01 22:34:14 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -65,7 +65,7 @@ uvm_pagegetdirty(struct vm_page *pg)
 	KASSERT((~pg->flags & (PG_CLEAN|PG_DIRTY)) != 0);
 	KASSERT(uvm_page_locked_p(pg));
 	KASSERT(uobj == NULL || ((pg->flags & PG_CLEAN) == 0) ==
-	    radix_tree_get_tag(&uobj->uo_pages, idx, UVM_PAGE_DIRTY_TAG));
+	    !!radix_tree_get_tag(&uobj->uo_pages, idx, UVM_PAGE_DIRTY_TAG));
 	return pg->flags & (PG_CLEAN|PG_DIRTY);
 }
 
@@ -104,7 +104,7 @@ uvm_pagemarkdirty(struct vm_page *pg, un
 	KASSERT((newstatus & ~(PG_CLEAN|PG_DIRTY)) == 0);
 	KASSERT(uvm_page_locked_p(pg));
 	KASSERT(uobj == NULL || ((pg->flags & PG_CLEAN) == 0) ==
-	    radix_tree_get_tag(&uobj->uo_pages, idx, UVM_PAGE_DIRTY_TAG));
+	    !!radix_tree_get_tag(&uobj->uo_pages, idx, UVM_PAGE_DIRTY_TAG));
 
 	if (oldstatus == newstatus) {
 		return;
@@ -131,7 +131,7 @@ uvm_pagemarkdirty(struct vm_page *pg, un
 	pg->flags &= ~(PG_CLEAN|PG_DIRTY);
 	pg->flags |= newstatus;
 	KASSERT(uobj == NULL || ((pg->flags & PG_CLEAN) == 0) ==
-	    radix_tree_get_tag(&uobj->uo_pages, idx, UVM_PAGE_DIRTY_TAG));
+	    !!radix_tree_get_tag(&uobj->uo_pages, idx, UVM_PAGE_DIRTY_TAG));
 	if ((pg->pqflags & PQ_STAT) != 0) {
 		stat_update((pg->pqflags & PQ_SWAPBACKED) != 0,
 		    oldstatus, newstatus);

Index: src/sys/uvm/uvm_pager.c
diff -u src/sys/uvm/uvm_pager.c:1.107.2.3 src/sys/uvm/uvm_pager.c:1.107.2.4
--- src/sys/uvm/uvm_pager.c:1.107.2.3	Tue Apr 17 00:09:00 2012
+++ src/sys/uvm/uvm_pager.c	Wed Aug  1 22:34:14 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_pager.c,v 1.107.2.3 2012/04/17 00:09:00 yamt Exp $	*/
+/*	$NetBSD: uvm_pager.c,v 1.107.2.4 2012/08/01 22:34:14 yamt Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_pager.c,v 1.107.2.3 2012/04/17 00:09:00 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_pager.c,v 1.107.2.4 2012/08/01 22:34:14 yamt Exp $");
 
 #include "opt_uvmhist.h"
 #include "opt_readahead.h"
@@ -368,6 +368,13 @@ uvm_aio_aiodone_pages(struct vm_page **p
 		}
 #endif /* defined(VMSWAP) */
 
+		if (write && uobj != NULL) {
+			KASSERT(radix_tree_get_tag(&uobj->uo_pages,
+			    pg->offset >> PAGE_SHIFT, UVM_PAGE_WRITEBACK_TAG));
+			radix_tree_clear_tag(&uobj->uo_pages,
+			    pg->offset >> PAGE_SHIFT, UVM_PAGE_WRITEBACK_TAG);
+		}
+
 		/*
 		 * process errors.  for reads, just mark the page to be freed.
 		 * for writes, if the error was ENOMEM, we assume this was

Index: src/sys/uvm/uvm_vnode.c
diff -u src/sys/uvm/uvm_vnode.c:1.97.2.6 src/sys/uvm/uvm_vnode.c:1.97.2.7
--- src/sys/uvm/uvm_vnode.c:1.97.2.6	Wed Aug  1 21:12:23 2012
+++ src/sys/uvm/uvm_vnode.c	Wed Aug  1 22:34:14 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_vnode.c,v 1.97.2.6 2012/08/01 21:12:23 yamt Exp $	*/
+/*	$NetBSD: uvm_vnode.c,v 1.97.2.7 2012/08/01 22:34:14 yamt Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -45,7 +45,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_vnode.c,v 1.97.2.6 2012/08/01 21:12:23 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_vnode.c,v 1.97.2.7 2012/08/01 22:34:14 yamt Exp $");
 
 #include "opt_uvmhist.h"
 
@@ -245,7 +245,7 @@ uvn_findpage(struct uvm_object *uobj, vo
 	const unsigned int fillflags =
 	    ((flags & UFP_BACKWARD) ? UVM_PAGE_ARRAY_FILL_BACKWARD : 0) |
 	    ((flags & UFP_DIRTYONLY) ?
-	    (UVM_PAGE_ARRAY_FILL_DIRTYONLY|UVM_PAGE_ARRAY_FILL_DENSE) : 0);
+	    (UVM_PAGE_ARRAY_FILL_DIRTY|UVM_PAGE_ARRAY_FILL_DENSE) : 0);
 	UVMHIST_FUNC("uvn_findpage"); UVMHIST_CALLED(ubchist);
 	UVMHIST_LOG(ubchist, "vp %p off 0x%lx", uobj, offset,0,0);
 

Reply via email to