Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/uvm - In ubc_alloc() take initial offset into account in...
details: https://anonhg.NetBSD.org/src/rev/20c2ad4fba33
branches: trunk
changeset: 933256:20c2ad4fba33
user: ad <ad%NetBSD.org@localhost>
date: Sat May 23 11:59:03 2020 +0000
description:
- In ubc_alloc() take initial offset into account in the UBC_FAULTBUSY case
or one too few pages can be mapped.
- In ubc_release() with UBC_FAULTBUSY, chances are that pages are newly
allocated and freshly enqueued, so avoid uvm_pageactivate() if possible
- Keep track of the pages mapped in ubc_alloc() in an array on the stack,
and use this to avoid calling pmap_extract() in ubc_release().
diffstat:
sys/uvm/uvm_bio.c | 72 ++++++++++++++++++++++++++++++++----------------------
1 files changed, 42 insertions(+), 30 deletions(-)
diffs (199 lines):
diff -r b214698249c7 -r 20c2ad4fba33 sys/uvm/uvm_bio.c
--- a/sys/uvm/uvm_bio.c Sat May 23 11:33:56 2020 +0000
+++ b/sys/uvm/uvm_bio.c Sat May 23 11:59:03 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_bio.c,v 1.114 2020/05/19 22:22:15 ad Exp $ */
+/* $NetBSD: uvm_bio.c,v 1.115 2020/05/23 11:59:03 ad Exp $ */
/*
* Copyright (c) 1998 Chuck Silvers.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.114 2020/05/19 22:22:15 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.115 2020/05/23 11:59:03 ad Exp $");
#include "opt_uvmhist.h"
#include "opt_ubc.h"
@@ -47,6 +47,7 @@
#include <sys/vnode.h>
#include <uvm/uvm.h>
+#include <uvm/uvm_pdpolicy.h>
#ifdef PMAP_DIRECT
# define UBC_USE_PMAP_DIRECT
@@ -472,7 +473,7 @@
static void * __noinline
ubc_alloc(struct uvm_object *uobj, voff_t offset, vsize_t *lenp, int advice,
- int flags)
+ int flags, struct vm_page **pgs, int *npagesp)
{
vaddr_t slot_offset, va;
struct ubc_map *umap;
@@ -487,6 +488,7 @@
umap_offset = (offset & ~((voff_t)ubc_winsize - 1));
slot_offset = (vaddr_t)(offset & ((voff_t)ubc_winsize - 1));
*lenp = MIN(*lenp, ubc_winsize - slot_offset);
+ KASSERT(*lenp > 0);
rw_enter(ubc_object.uobj.vmobjlock, RW_WRITER);
again:
@@ -560,14 +562,14 @@
(uintptr_t)umap, umap->refcount, (uintptr_t)va, flags);
if (flags & UBC_FAULTBUSY) {
- // XXX add offset from slot_offset?
- int npages = (*lenp + PAGE_SIZE - 1) >> PAGE_SHIFT;
- struct vm_page *pgs[npages];
+ int npages = (*lenp + (offset & (PAGE_SIZE - 1)) +
+ PAGE_SIZE - 1) >> PAGE_SHIFT;
int gpflags =
PGO_SYNCIO|PGO_OVERWRITE|PGO_PASTEOF|PGO_NOBLOCKALLOC|
PGO_NOTIMESTAMP;
int i;
KDASSERT(flags & UBC_WRITE);
+ KASSERT(npages <= *npagesp);
KASSERT(umap->refcount == 1);
UBC_EVCNT_INCR(faultbusy);
@@ -577,7 +579,7 @@
umap->flags &= ~UMAP_MAPPING_CACHED;
pmap_remove(pmap_kernel(), va, va + ubc_winsize);
}
- memset(pgs, 0, sizeof(pgs));
+ memset(pgs, 0, *npagesp * sizeof(pgs[0]));
error = (*uobj->pgops->pgo_get)(uobj, trunc_page(offset), pgs,
&npages, 0, VM_PROT_READ | VM_PROT_WRITE, advice, gpflags);
@@ -615,6 +617,7 @@
}
pmap_update(pmap_kernel());
umap->flags |= UMAP_PAGES_LOCKED;
+ *npagesp = npages;
} else {
KASSERT((umap->flags & UMAP_PAGES_LOCKED) == 0);
}
@@ -628,7 +631,7 @@
*/
static void __noinline
-ubc_release(void *va, int flags)
+ubc_release(void *va, int flags, struct vm_page **pgs, int npages)
{
struct ubc_map *umap;
struct uvm_object *uobj;
@@ -643,13 +646,11 @@
KASSERT(uobj != NULL);
if (umap->flags & UMAP_PAGES_LOCKED) {
- const voff_t slot_offset = umap->writeoff;
const voff_t endoff = umap->writeoff + umap->writelen;
const voff_t zerolen = round_page(endoff) - endoff;
- const u_int npages = (round_page(endoff) -
- trunc_page(slot_offset)) >> PAGE_SHIFT;
- struct vm_page *pgs[npages];
+ KASSERT(npages == (round_page(endoff) -
+ trunc_page(umap->writeoff)) >> PAGE_SHIFT);
KASSERT((umap->flags & UMAP_MAPPING_CACHED) == 0);
if (zerolen) {
memset((char *)umapva + endoff, 0, zerolen);
@@ -657,21 +658,25 @@
umap->flags &= ~UMAP_PAGES_LOCKED;
rw_enter(uobj->vmobjlock, RW_WRITER);
for (u_int i = 0; i < npages; i++) {
+ struct vm_page *pg = pgs[i];
+#ifdef DIAGNOSTIC
paddr_t pa;
- bool rv __diagused;
-
- rv = pmap_extract(pmap_kernel(),
- umapva + slot_offset + (i << PAGE_SHIFT), &pa);
+ bool rv;
+ rv = pmap_extract(pmap_kernel(), umapva +
+ umap->writeoff + (i << PAGE_SHIFT), &pa);
KASSERT(rv);
- pgs[i] = PHYS_TO_VM_PAGE(pa);
- pgs[i]->flags &= ~PG_FAKE;
- KASSERTMSG(uvm_pagegetdirty(pgs[i]) ==
+ KASSERT(PHYS_TO_VM_PAGE(pa) == pg);
+#endif
+ pg->flags &= ~PG_FAKE;
+ KASSERTMSG(uvm_pagegetdirty(pg) ==
UVM_PAGE_STATUS_DIRTY,
- "page %p not dirty", pgs[i]);
- KASSERT(pgs[i]->loan_count == 0);
- uvm_pagelock(pgs[i]);
- uvm_pageactivate(pgs[i]);
- uvm_pageunlock(pgs[i]);
+ "page %p not dirty", pg);
+ KASSERT(pg->loan_count == 0);
+ if (uvmpdpol_pageactivate_p(pg)) {
+ uvm_pagelock(pg);
+ uvm_pageactivate(pg);
+ uvm_pageunlock(pg);
+ }
}
pmap_kremove(umapva, ubc_winsize);
pmap_update(pmap_kernel());
@@ -727,8 +732,9 @@
int flags)
{
const bool overwrite = (flags & UBC_FAULTBUSY) != 0;
+ struct vm_page *pgs[ubc_winsize >> PAGE_SHIFT];
voff_t off;
- int error;
+ int error, npages;
KASSERT(todo <= uio->uio_resid);
KASSERT(((flags & UBC_WRITE) != 0 && uio->uio_rw == UIO_WRITE) ||
@@ -755,7 +761,9 @@
vsize_t bytelen = todo;
void *win;
- win = ubc_alloc(uobj, off, &bytelen, advice, flags);
+ npages = __arraycount(pgs);
+ win = ubc_alloc(uobj, off, &bytelen, advice, flags, pgs,
+ &npages);
if (error == 0) {
error = uiomove(win, bytelen, uio);
}
@@ -768,7 +776,7 @@
printf("%s: error=%d\n", __func__, error);
memset(win, 0, bytelen);
}
- ubc_release(win, flags);
+ ubc_release(win, flags, pgs, npages);
off += bytelen;
todo -= bytelen;
if (error != 0 && (flags & UBC_PARTIALOK) != 0) {
@@ -786,9 +794,11 @@
void
ubc_zerorange(struct uvm_object *uobj, off_t off, size_t len, int flags)
{
+ struct vm_page *pgs[ubc_winsize >> PAGE_SHIFT];
+ int npages;
#ifdef UBC_USE_PMAP_DIRECT
- if (ubc_direct) {
+ if (ubc_direct || (flags & UBC_FAULTBUSY) != 0) {
ubc_zerorange_direct(uobj, off, len, flags);
return;
}
@@ -802,9 +812,11 @@
void *win;
vsize_t bytelen = len;
- win = ubc_alloc(uobj, off, &bytelen, UVM_ADV_NORMAL, UBC_WRITE);
+ npages = __arraycount(pgs);
+ win = ubc_alloc(uobj, off, &bytelen, UVM_ADV_NORMAL, UBC_WRITE,
+ pgs, &npages);
memset(win, 0, bytelen);
- ubc_release(win, flags);
+ ubc_release(win, flags, pgs, npages);
off += bytelen;
len -= bytelen;
Home |
Main Index |
Thread Index |
Old Index