Module Name: src
Committed By: ad
Date: Tue May 19 21:52:04 UTC 2020
Modified Files:
src/sys/uvm: uvm_loan.c
Log Message:
uvm_loanuobjpages():
- vmobjlock is shared between tmpfs vnodes and UAOs now
- split into two routines, to simplify
- fix error recovery
To generate a diff of this commit:
cvs rdiff -u -r1.101 -r1.102 src/sys/uvm/uvm_loan.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/uvm/uvm_loan.c
diff -u src/sys/uvm/uvm_loan.c:1.101 src/sys/uvm/uvm_loan.c:1.102
--- src/sys/uvm/uvm_loan.c:1.101 Sun May 17 19:38:17 2020
+++ src/sys/uvm/uvm_loan.c Tue May 19 21:52:04 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_loan.c,v 1.101 2020/05/17 19:38:17 ad Exp $ */
+/* $NetBSD: uvm_loan.c,v 1.102 2020/05/19 21:52:04 ad Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_loan.c,v 1.101 2020/05/17 19:38:17 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_loan.c,v 1.102 2020/05/19 21:52:04 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -505,101 +505,81 @@ uvm_loanpage(struct vm_page **pgpp, int
#define UVM_LOAN_GET_CHUNK 16
/*
- * uvm_loanuobjpages: loan pages from a uobj out (O->K)
- *
- * => uobj shouldn't be locked. (we'll lock it)
- * => fail with EBUSY if we meet a wired page.
+ * uvm_loanuobjchunk: helper for uvm_loanuobjpages()
*/
-int
-uvm_loanuobjpages(struct uvm_object *uobj, voff_t pgoff, int orignpages,
- struct vm_page **origpgpp)
+static int
+uvm_loanuobjchunk(struct uvm_object *uobj, voff_t pgoff, int orignpages,
+ struct vm_page **pgpp)
{
- int ndone; /* # of pages loaned out */
- struct vm_page **pgpp;
- int error;
- int i;
- krwlock_t *slock;
-
- pgpp = origpgpp;
- for (ndone = 0; ndone < orignpages; ) {
- int npages;
- /* npendloan: # of pages busied but not loand out yet. */
- int npendloan = 0xdead; /* XXX gcc */
-reget:
- npages = MIN(UVM_LOAN_GET_CHUNK, orignpages - ndone);
- rw_enter(uobj->vmobjlock, RW_WRITER);
- error = (*uobj->pgops->pgo_get)(uobj,
- pgoff + (ndone << PAGE_SHIFT), pgpp, &npages, 0,
- VM_PROT_READ, 0, PGO_SYNCIO);
- if (error == EAGAIN) {
- kpause("loanuopg", false, hz/2, NULL);
- continue;
- }
- if (error)
- goto fail;
-
- KASSERT(npages > 0);
+ int error, npages;
- /* loan and unbusy pages */
- slock = NULL;
- for (i = 0; i < npages; i++) {
- krwlock_t *nextslock; /* slock for next page */
- struct vm_page *pg = *pgpp;
-
- /* XXX assuming that the page is owned by uobj */
- KASSERT(pg->uobject != NULL);
- nextslock = pg->uobject->vmobjlock;
-
- if (slock != nextslock) {
- if (slock) {
- KASSERT(npendloan > 0);
- error = uvm_loanpage(pgpp - npendloan,
- npendloan, true);
- rw_exit(slock);
- if (error)
- goto fail;
- ndone += npendloan;
- KASSERT(origpgpp + ndone == pgpp);
- }
- slock = nextslock;
- npendloan = 0;
- rw_enter(slock, RW_WRITER);
- }
+ rw_enter(uobj->vmobjlock, RW_WRITER);
+ reget:
+ npages = orignpages;
+ error = (*uobj->pgops->pgo_get)(uobj, pgoff, pgpp, &npages, 0,
+ VM_PROT_READ, 0, PGO_SYNCIO);
+ switch (error) {
+ case 0:
+ KASSERT(npages == orignpages);
- if ((pg->flags & PG_RELEASED) != 0) {
+ /* check for released pages */
+ rw_enter(uobj->vmobjlock, RW_WRITER);
+ for (int i = 0; i < npages; i++) {
+ KASSERT(pgpp[i]->uobject->vmobjlock == uobj->vmobjlock);
+ if ((pgpp[i]->flags & PG_RELEASED) != 0) {
/*
* release pages and try again.
*/
- rw_exit(slock);
- for (; i < npages; i++) {
- pg = pgpp[i];
- slock = pg->uobject->vmobjlock;
-
- rw_enter(slock, RW_WRITER);
- uvm_page_unbusy(&pg, 1);
- rw_exit(slock);
- }
+ uvm_page_unbusy(pgpp, npages);
goto reget;
}
+ }
- npendloan++;
- pgpp++;
- KASSERT(origpgpp + ndone + npendloan == pgpp);
- }
- KASSERT(slock != NULL);
- KASSERT(npendloan > 0);
- error = uvm_loanpage(pgpp - npendloan, npendloan, true);
- rw_exit(slock);
- if (error)
- goto fail;
- ndone += npendloan;
- KASSERT(origpgpp + ndone == pgpp);
+ /* loan out pages. they will be unbusied whatever happens. */
+ error = uvm_loanpage(pgpp, npages, true);
+ rw_exit(uobj->vmobjlock);
+ return error;
+
+ case EAGAIN:
+ kpause("loanuopg", false, hz/2, NULL);
+ rw_enter(uobj->vmobjlock, RW_WRITER);
+ goto reget;
+
+ default:
+ if (npages > 0) {
+ rw_enter(uobj->vmobjlock, RW_WRITER);
+ uvm_page_unbusy(pgpp, npages);
+ rw_exit(uobj->vmobjlock);
+ }
+ return error;
}
+}
- return 0;
+/*
+ * uvm_loanuobjpages: loan pages from a uobj out (O->K)
+ *
+ * => uobj shouldn't be locked. (we'll lock it)
+ * => fail with EBUSY if we meet a wired page.
+ */
+int
+uvm_loanuobjpages(struct uvm_object *uobj, voff_t pgoff, int npages,
+ struct vm_page **pgpp)
+{
+ int ndone, error, chunk;
-fail:
- uvm_unloan(origpgpp, ndone, UVM_LOAN_TOPAGE);
+ KASSERT(npages > 0);
+
+ for (ndone = 0; ndone < npages; ndone += chunk) {
+ chunk = MIN(UVM_LOAN_GET_CHUNK, npages - ndone);
+ error = uvm_loanuobjchunk(uobj, pgoff + (ndone << PAGE_SHIFT),
+ chunk, pgpp + ndone);
+ if (error != 0) {
+ if (ndone != 0) {
+ uvm_unloan(pgpp, ndone, UVM_LOAN_TOPAGE);
+ }
+ break;
+ }
+ }
return error;
}