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; }