aboutsummaryrefslogtreecommitdiff
path: root/sys/vm
diff options
context:
space:
mode:
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_extern.h2
-rw-r--r--sys/vm/vm_fault.c81
-rw-r--r--sys/vm/vm_page.c12
-rw-r--r--sys/vm/vnode_pager.c5
4 files changed, 73 insertions, 27 deletions
diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h
index 93ec6014c27d..2b15a01206a2 100644
--- a/sys/vm/vm_extern.h
+++ b/sys/vm/vm_extern.h
@@ -91,6 +91,8 @@ void vm_fault_copy_entry(vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t,
vm_ooffset_t *);
int vm_fault_disable_pagefaults(void);
void vm_fault_enable_pagefaults(int save);
+int vm_fault_hold_pages_e(vm_map_t map, vm_offset_t addr, vm_size_t len,
+ vm_prot_t prot, vm_page_t *ma, int max_count, int *ppages_count);
int vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len,
vm_prot_t prot, vm_page_t *ma, int max_count);
int vm_fault_trap(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type,
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 3e57e8d4f1d0..2a27f3e674a4 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -1995,32 +1995,43 @@ vm_fault_prefault(const struct faultstate *fs, vm_offset_t addra,
}
/*
- * Hold each of the physical pages that are mapped by the specified range of
- * virtual addresses, ["addr", "addr" + "len"), if those mappings are valid
- * and allow the specified types of access, "prot". If all of the implied
- * pages are successfully held, then the number of held pages is returned
- * together with pointers to those pages in the array "ma". However, if any
- * of the pages cannot be held, -1 is returned.
+ * Hold each of the physical pages that are mapped by the specified
+ * range of virtual addresses, ["addr", "addr" + "len"), if those
+ * mappings are valid and allow the specified types of access, "prot".
+ * If all of the implied pages are successfully held, then the number
+ * of held pages is assigned to *ppages_count, together with pointers
+ * to those pages in the array "ma". The returned value is zero.
+ *
+ * However, if any of the pages cannot be held, an error is returned,
+ * and no pages are held.
+ * Error values:
+ * ENOMEM - the range is not valid
+ * EINVAL - the provided vm_page array is too small to hold all pages
+ * EAGAIN - a page was not mapped, and the thread is in nofaulting mode
+ * EFAULT - a page with requested permissions cannot be mapped
+ * (more detailed result from vm_fault() is lost)
*/
int
-vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len,
- vm_prot_t prot, vm_page_t *ma, int max_count)
+vm_fault_hold_pages_e(vm_map_t map, vm_offset_t addr, vm_size_t len,
+ vm_prot_t prot, vm_page_t *ma, int max_count, int *ppages_count)
{
vm_offset_t end, va;
vm_page_t *mp;
- int count;
+ int count, error;
boolean_t pmap_failed;
- if (len == 0)
+ if (len == 0) {
+ *ppages_count = 0;
return (0);
+ }
end = round_page(addr + len);
addr = trunc_page(addr);
if (!vm_map_range_valid(map, addr, end))
- return (-1);
+ return (ENOMEM);
if (atop(end - addr) > max_count)
- panic("vm_fault_quick_hold_pages: count > max_count");
+ return (EINVAL);
count = atop(end - addr);
/*
@@ -2062,19 +2073,49 @@ vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len,
* the proper behaviour explicitly.
*/
if ((prot & VM_PROT_QUICK_NOFAULT) != 0 &&
- (curthread->td_pflags & TDP_NOFAULTING) != 0)
- goto error;
- for (mp = ma, va = addr; va < end; mp++, va += PAGE_SIZE)
+ (curthread->td_pflags & TDP_NOFAULTING) != 0) {
+ error = EAGAIN;
+ goto fail;
+ }
+ for (mp = ma, va = addr; va < end; mp++, va += PAGE_SIZE) {
if (*mp == NULL && vm_fault(map, va, prot,
- VM_FAULT_NORMAL, mp) != KERN_SUCCESS)
- goto error;
+ VM_FAULT_NORMAL, mp) != KERN_SUCCESS) {
+ error = EFAULT;
+ goto fail;
+ }
+ }
}
- return (count);
-error:
+ *ppages_count = count;
+ return (0);
+fail:
for (mp = ma; mp < ma + count; mp++)
if (*mp != NULL)
vm_page_unwire(*mp, PQ_INACTIVE);
- return (-1);
+ return (error);
+}
+
+ /*
+ * Hold each of the physical pages that are mapped by the specified range of
+ * virtual addresses, ["addr", "addr" + "len"), if those mappings are valid
+ * and allow the specified types of access, "prot". If all of the implied
+ * pages are successfully held, then the number of held pages is returned
+ * together with pointers to those pages in the array "ma". However, if any
+ * of the pages cannot be held, -1 is returned.
+ */
+int
+vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len,
+ vm_prot_t prot, vm_page_t *ma, int max_count)
+{
+ int error, pages_count;
+
+ error = vm_fault_hold_pages_e(map, addr, len, prot, ma,
+ max_count, &pages_count);
+ if (error != 0) {
+ if (error == EINVAL)
+ panic("vm_fault_quick_hold_pages: count > max_count");
+ return (-1);
+ }
+ return (pages_count);
}
/*
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index b239a6ffb4ce..abad5efb8a79 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -394,11 +394,15 @@ vm_page_blacklist_load(char **list, char **end)
ptr = preload_fetch_addr(mod);
len = preload_fetch_size(mod);
}
- *list = ptr;
- if (ptr != NULL)
+
+ if (ptr != NULL && len > 0) {
+ *list = ptr;
*end = ptr + len - 1;
- else
+ } else {
+ *list = NULL;
*end = NULL;
+ }
+
return;
}
@@ -4713,7 +4717,7 @@ vm_page_grab_pflags(int allocflags)
pflags = allocflags &
~(VM_ALLOC_NOWAIT | VM_ALLOC_WAITOK | VM_ALLOC_WAITFAIL |
- VM_ALLOC_NOBUSY | VM_ALLOC_IGN_SBUSY);
+ VM_ALLOC_NOBUSY | VM_ALLOC_IGN_SBUSY | VM_ALLOC_NOCREAT);
if ((allocflags & VM_ALLOC_NOWAIT) == 0)
pflags |= VM_ALLOC_WAITFAIL;
if ((allocflags & VM_ALLOC_IGN_SBUSY) != 0)
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 24e3bef07f7c..244aa31ea703 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -502,7 +502,7 @@ vnode_pager_setsize(struct vnode *vp, vm_ooffset_t nsize)
if ((object = vp->v_object) == NULL)
return;
-#ifdef DEBUG_VFS_LOCKS
+#ifdef INVARIANTS
{
struct mount *mp;
@@ -901,8 +901,7 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
int error, before, after, rbehind, rahead, poff, i;
int bytecount, secmask;
- KASSERT(vp->v_type != VCHR && vp->v_type != VBLK,
- ("%s does not support devices", __func__));
+ KASSERT(!VN_ISDEV(vp), ("%s does not support devices", __func__));
if (VN_IS_DOOMED(vp))
return (VM_PAGER_BAD);