summaryrefslogtreecommitdiff
path: root/sys/vm
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2010-11-26 15:30:02 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2010-11-26 15:30:02 +0000
commit95507db69b5aa053ad8deb9b63c1dfb963831bf2 (patch)
tree44f61e87134f725b54e1f62314dbac05a64f6189 /sys/vm
parenta38445758921849e6a753764413155b544cfb870 (diff)
Notes
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_contig.c2
-rw-r--r--sys/vm/vm_object.c75
-rw-r--r--sys/vm/vm_pageout.c16
-rw-r--r--sys/vm/vm_pageout.h2
4 files changed, 33 insertions, 62 deletions
diff --git a/sys/vm/vm_contig.c b/sys/vm/vm_contig.c
index 78d7e2808364..ed3e16960a7a 100644
--- a/sys/vm/vm_contig.c
+++ b/sys/vm/vm_contig.c
@@ -138,7 +138,7 @@ vm_contig_launder_page(vm_page_t m, vm_page_t *next)
} else if (object->type == OBJT_SWAP ||
object->type == OBJT_DEFAULT) {
m_tmp = m;
- vm_pageout_flush(&m_tmp, 1, VM_PAGER_PUT_SYNC);
+ vm_pageout_flush(&m_tmp, 1, VM_PAGER_PUT_SYNC, 0, NULL);
VM_OBJECT_UNLOCK(object);
return (0);
}
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index def983c59fae..a7d230abe8ff 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -809,10 +809,12 @@ rescan:
np = TAILQ_NEXT(p, listq);
if (p->valid == 0)
continue;
- while (vm_page_sleep_if_busy(p, TRUE, "vpcwai")) {
+ if (vm_page_sleep_if_busy(p, TRUE, "vpcwai")) {
vm_page_lock_queues();
if (object->generation != curgeneration)
goto rescan;
+ np = vm_page_find_least(object, pi);
+ continue;
}
vm_page_test_dirty(p);
if (p->dirty == 0)
@@ -828,7 +830,6 @@ rescan:
continue;
n = vm_object_page_collect_flush(object, p, pagerflags);
- KASSERT(n > 0, ("vm_object_page_collect_flush failed"));
if (object->generation != curgeneration)
goto rescan;
np = vm_page_find_least(object, pi + n);
@@ -844,77 +845,39 @@ rescan:
static int
vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int pagerflags)
{
- int runlen;
- int maxf;
- int chkb;
- int maxb;
- int i, index;
- vm_pindex_t pi;
- vm_page_t maf[vm_pageout_page_count];
- vm_page_t mab[vm_pageout_page_count];
- vm_page_t ma[vm_pageout_page_count];
- vm_page_t tp, p1;
+ vm_page_t ma[vm_pageout_page_count], p_first, tp;
+ int count, i, mreq, runlen;
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
- pi = p->pindex;
- maxf = 0;
- for (i = 1, p1 = p; i < vm_pageout_page_count; i++) {
- tp = vm_page_next(p1);
+
+ count = 1;
+ mreq = 0;
+
+ for (tp = p; count < vm_pageout_page_count; count++) {
+ tp = vm_page_next(tp);
if (tp == NULL || tp->busy != 0 || (tp->oflags & VPO_BUSY) != 0)
break;
vm_page_test_dirty(tp);
if (tp->dirty == 0)
break;
- maf[i - 1] = p1 = tp;
- maxf++;
}
- maxb = 0;
- chkb = vm_pageout_page_count - maxf;
- for (i = 1, p1 = p; i < chkb; i++) {
- tp = vm_page_prev(p1);
+ for (p_first = p; count < vm_pageout_page_count; count++) {
+ tp = vm_page_prev(p_first);
if (tp == NULL || tp->busy != 0 || (tp->oflags & VPO_BUSY) != 0)
break;
vm_page_test_dirty(tp);
if (tp->dirty == 0)
break;
- mab[i - 1] = p1 = tp;
- maxb++;
+ p_first = tp;
+ mreq++;
}
- for (i = 0; i < maxb; i++) {
- index = (maxb - i) - 1;
- ma[index] = mab[i];
- }
- ma[maxb] = p;
- for (i = 0; i < maxf; i++) {
- index = (maxb + i) + 1;
- ma[index] = maf[i];
- }
- runlen = maxb + maxf + 1;
+ for (tp = p_first, i = 0; i < count; tp = TAILQ_NEXT(tp, listq), i++)
+ ma[i] = tp;
- vm_pageout_flush(ma, runlen, pagerflags);
- for (i = 0; i < runlen; i++) {
- if (ma[i]->dirty != 0) {
- KASSERT((ma[i]->flags & PG_WRITEABLE) == 0,
- ("vm_object_page_collect_flush: page %p is not write protected",
- ma[i]));
- }
- }
- for (i = 0; i < maxf; i++) {
- if (ma[i + maxb + 1]->dirty != 0) {
- /*
- * maxf will end up being the actual number of pages
- * we wrote out contiguously, non-inclusive of the
- * first page. We do not count look-behind pages.
- */
- if (maxf > i) {
- maxf = i;
- break;
- }
- }
- }
- return (maxf + 1);
+ vm_pageout_flush(ma, count, pagerflags, mreq, &runlen);
+ return (runlen);
}
/*
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 314c98640a54..23f53a4a2e09 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -391,7 +391,7 @@ more:
/*
* we allow reads during pageouts...
*/
- return (vm_pageout_flush(&mc[page_base], pageout_count, 0));
+ return (vm_pageout_flush(&mc[page_base], pageout_count, 0, 0, NULL));
}
/*
@@ -402,14 +402,17 @@ more:
* reference count all in here rather then in the parent. If we want
* the parent to do more sophisticated things we may have to change
* the ordering.
+ *
+ * Returned runlen is the count of pages between mreq and first
+ * page after mreq with status VM_PAGER_AGAIN.
*/
int
-vm_pageout_flush(vm_page_t *mc, int count, int flags)
+vm_pageout_flush(vm_page_t *mc, int count, int flags, int mreq, int *prunlen)
{
vm_object_t object = mc[0]->object;
int pageout_status[count];
int numpagedout = 0;
- int i;
+ int i, runlen;
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
@@ -435,6 +438,7 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags)
vm_pager_put_pages(object, mc, count, flags, pageout_status);
+ runlen = count - mreq;
vm_page_lock_queues();
for (i = 0; i < count; i++) {
vm_page_t mt = mc[i];
@@ -465,6 +469,8 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags)
vm_page_activate(mt);
break;
case VM_PAGER_AGAIN:
+ if (i >= mreq && i - mreq < runlen)
+ runlen = i - mreq;
break;
}
@@ -481,7 +487,9 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags)
vm_page_try_to_cache(mt);
}
}
- return numpagedout;
+ if (prunlen != NULL)
+ *prunlen = runlen;
+ return (numpagedout);
}
#if !defined(NO_SWAPPING)
diff --git a/sys/vm/vm_pageout.h b/sys/vm/vm_pageout.h
index 15ca5708a0c0..b9dafa0f1860 100644
--- a/sys/vm/vm_pageout.h
+++ b/sys/vm/vm_pageout.h
@@ -102,7 +102,7 @@ extern void vm_waitpfault(void);
#ifdef _KERNEL
boolean_t vm_pageout_fallback_object_lock(vm_page_t, vm_page_t *);
-int vm_pageout_flush(vm_page_t *, int, int);
+int vm_pageout_flush(vm_page_t *, int, int, int, int *);
void vm_pageout_oom(int shortage);
#endif
#endif /* _VM_VM_PAGEOUT_H_ */