summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2017-10-07 18:08:37 +0000
committerLuiz Souza <luiz@netgate.com>2018-02-21 15:14:46 -0300
commit54ab4cf70b3991bc5f1fe088248ee2069954f3ab (patch)
treef6ddf3e228e2f10ca0239e20420599f97fd6d9de /sys/vm
parent77c23f6c7df09a861b606acaa485ba1ab8883533 (diff)
downloadFreeBSD-src-54ab4cf70b3991bc5f1fe088248ee2069954f3ab.zip
FreeBSD-src-54ab4cf70b3991bc5f1fe088248ee2069954f3ab.tar.gz
MFC r320980,321377
Generalize vm_page_ps_is_valid() to support testing other predicates on the (super)page, renaming the function to vm_page_ps_test(). In vm_page_ps_test(), always check that the base pages within the specified superpage all belong to the same object. To date, that check has not been needed, but upcoming changes require it. (cherry picked from commit 8df894b522e2199c482090bcc1064dadc3259a72)
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_map.c2
-rw-r--r--sys/vm/vm_page.c37
-rw-r--r--sys/vm/vm_page.h14
3 files changed, 42 insertions, 11 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 5dc76d1..1290b21 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -1962,7 +1962,7 @@ vm_map_pmap_enter(vm_map_t map, vm_offset_t addr, vm_prot_t prot,
(pagesizes[p->psind] - 1)) == 0) {
mask = atop(pagesizes[p->psind]) - 1;
if (tmpidx + mask < psize &&
- vm_page_ps_is_valid(p)) {
+ vm_page_ps_test(p, PS_ALL_VALID, NULL)) {
p += mask;
threshold += mask;
}
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 155d1a8..1affc06 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -3612,16 +3612,17 @@ vm_page_is_valid(vm_page_t m, int base, int size)
}
/*
- * vm_page_ps_is_valid:
- *
- * Returns TRUE if the entire (super)page is valid and FALSE otherwise.
+ * Returns true if all of the specified predicates are true for the entire
+ * (super)page and false otherwise.
*/
-boolean_t
-vm_page_ps_is_valid(vm_page_t m)
+bool
+vm_page_ps_test(vm_page_t m, int flags, vm_page_t skip_m)
{
+ vm_object_t object;
int i, npages;
- VM_OBJECT_ASSERT_LOCKED(m->object);
+ object = m->object;
+ VM_OBJECT_ASSERT_LOCKED(object);
npages = atop(pagesizes[m->psind]);
/*
@@ -3630,10 +3631,28 @@ vm_page_ps_is_valid(vm_page_t m)
* occupy adjacent entries in vm_page_array[].
*/
for (i = 0; i < npages; i++) {
- if (m[i].valid != VM_PAGE_BITS_ALL)
- return (FALSE);
+ /* Always test object consistency, including "skip_m". */
+ if (m[i].object != object)
+ return (false);
+ if (&m[i] == skip_m)
+ continue;
+ if ((flags & PS_NONE_BUSY) != 0 && vm_page_busied(&m[i]))
+ return (false);
+ if ((flags & PS_ALL_DIRTY) != 0) {
+ /*
+ * Calling vm_page_test_dirty() or pmap_is_modified()
+ * might stop this case from spuriously returning
+ * "false". However, that would require a write lock
+ * on the object containing "m[i]".
+ */
+ if (m[i].dirty != VM_PAGE_BITS_ALL)
+ return (false);
+ }
+ if ((flags & PS_ALL_VALID) != 0 &&
+ m[i].valid != VM_PAGE_BITS_ALL)
+ return (false);
}
- return (TRUE);
+ return (true);
}
/*
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index e0ae041..38d625c 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -437,6 +437,18 @@ malloc2vm_flags(int malloc_flags)
}
#endif
+/*
+ * Predicates supported by vm_page_ps_test():
+ *
+ * PS_ALL_DIRTY is true only if the entire (super)page is dirty.
+ * However, it can be spuriously false when the (super)page has become
+ * dirty in the pmap but that information has not been propagated to the
+ * machine-independent layer.
+ */
+#define PS_ALL_DIRTY 0x1
+#define PS_ALL_VALID 0x2
+#define PS_NONE_BUSY 0x4
+
void vm_page_busy_downgrade(vm_page_t m);
void vm_page_busy_sleep(vm_page_t m, const char *msg, bool nonshared);
void vm_page_flash(vm_page_t m);
@@ -472,7 +484,7 @@ vm_page_t vm_page_next(vm_page_t m);
int vm_page_pa_tryrelock(pmap_t, vm_paddr_t, vm_paddr_t *);
struct vm_pagequeue *vm_page_pagequeue(vm_page_t m);
vm_page_t vm_page_prev(vm_page_t m);
-boolean_t vm_page_ps_is_valid(vm_page_t m);
+bool vm_page_ps_test(vm_page_t m, int flags, vm_page_t skip_m);
void vm_page_putfake(vm_page_t m);
void vm_page_readahead_finish(vm_page_t m);
bool vm_page_reclaim_contig(int req, u_long npages, vm_paddr_t low,
OpenPOWER on IntegriCloud