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