Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/yamt-pagecache]: src/sys - fix integrity sync.



details:   https://anonhg.NetBSD.org/src/rev/3c49750403be
branches:  yamt-pagecache
changeset: 770886:3c49750403be
user:      yamt <yamt%NetBSD.org@localhost>
date:      Wed Aug 01 22:34:14 2012 +0000

description:
- 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.

diffstat:

 sys/miscfs/genfs/genfs_io.c |  96 ++++++++++++++++++++++++++++++---------------
 sys/uvm/uvm_object.h        |   7 +-
 sys/uvm/uvm_page_array.c    |  13 ++++-
 sys/uvm/uvm_page_array.h    |   9 ++-
 sys/uvm/uvm_page_status.c   |  10 ++--
 sys/uvm/uvm_pager.c         |  11 ++++-
 sys/uvm/uvm_vnode.c         |   6 +-
 7 files changed, 99 insertions(+), 53 deletions(-)

diffs (truncated from 371 to 300 lines):

diff -r fc75f94e8045 -r 3c49750403be sys/miscfs/genfs/genfs_io.c
--- a/sys/miscfs/genfs/genfs_io.c       Wed Aug 01 21:13:45 2012 +0000
+++ b/sys/miscfs/genfs/genfs_io.c       Wed Aug 01 22:34:14 2012 +0000
@@ -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 @@
        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 @@
        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 @@
        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 @@
                                 */
                                break;
                        }
+                       /*
+                        * 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 */
-                       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();
-                       }
+                       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 @@
                            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 @@
 #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 @@
        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);
diff -r fc75f94e8045 -r 3c49750403be sys/uvm/uvm_object.h
--- a/sys/uvm/uvm_object.h      Wed Aug 01 21:13:45 2012 +0000
+++ b/sys/uvm/uvm_object.h      Wed Aug 01 22:34:14 2012 +0000
@@ -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 @@
 };
 
 /*
- * 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
diff -r fc75f94e8045 -r 3c49750403be sys/uvm/uvm_page_array.c
--- a/sys/uvm/uvm_page_array.c  Wed Aug 01 21:13:45 2012 +0000
+++ b/sys/uvm/uvm_page_array.c  Wed Aug 01 22:34:14 2012 +0000
@@ -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 @@
        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 :
diff -r fc75f94e8045 -r 3c49750403be sys/uvm/uvm_page_array.h
--- a/sys/uvm/uvm_page_array.h  Wed Aug 01 21:13:45 2012 +0000
+++ b/sys/uvm/uvm_page_array.h  Wed Aug 01 22:34:14 2012 +0000
@@ -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 @@
 /*
  * 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_) */
diff -r fc75f94e8045 -r 3c49750403be sys/uvm/uvm_page_status.c
--- a/sys/uvm/uvm_page_status.c Wed Aug 01 21:13:45 2012 +0000
+++ b/sys/uvm/uvm_page_status.c Wed Aug 01 22:34:14 2012 +0000
@@ -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 @@
        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 @@
        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));



Home | Main Index | Thread Index | Old Index