Module Name: src
Committed By: ad
Date: Tue May 19 22:22:15 UTC 2020
Modified Files:
src/sys/fs/tmpfs: tmpfs_vnops.c
src/sys/uvm: uvm_aobj.c uvm_bio.c uvm_object.c uvm_pager.h uvm_vnode.c
Log Message:
PR kern/32166: pgo_get protocol is ambiguous
Also problems with tmpfs+nfs noted by hannken@.
Don't pass PGO_ALLPAGES to pgo_get, and ignore PGO_DONTCARE in the
!PGO_LOCKED case. In uao_get() have uvm_pagealloc() take care of page
zeroing and release busy pages on error.
To generate a diff of this commit:
cvs rdiff -u -r1.140 -r1.141 src/sys/fs/tmpfs/tmpfs_vnops.c
cvs rdiff -u -r1.141 -r1.142 src/sys/uvm/uvm_aobj.c
cvs rdiff -u -r1.113 -r1.114 src/sys/uvm/uvm_bio.c
cvs rdiff -u -r1.21 -r1.22 src/sys/uvm/uvm_object.c
cvs rdiff -u -r1.48 -r1.49 src/sys/uvm/uvm_pager.h
cvs rdiff -u -r1.112 -r1.113 src/sys/uvm/uvm_vnode.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/fs/tmpfs/tmpfs_vnops.c
diff -u src/sys/fs/tmpfs/tmpfs_vnops.c:1.140 src/sys/fs/tmpfs/tmpfs_vnops.c:1.141
--- src/sys/fs/tmpfs/tmpfs_vnops.c:1.140 Sun May 17 19:43:31 2020
+++ src/sys/fs/tmpfs/tmpfs_vnops.c Tue May 19 22:22:15 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: tmpfs_vnops.c,v 1.140 2020/05/17 19:43:31 ad Exp $ */
+/* $NetBSD: tmpfs_vnops.c,v 1.141 2020/05/19 22:22:15 ad Exp $ */
/*
* Copyright (c) 2005, 2006, 2007, 2020 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.140 2020/05/17 19:43:31 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.141 2020/05/19 22:22:15 ad Exp $");
#include <sys/param.h>
#include <sys/dirent.h>
@@ -1234,20 +1234,10 @@ tmpfs_getpages(void *v)
tmpfs_update_lazily(vp, tflags);
}
- /*
- * Invoke the pager.
- *
- * Clean the array of pages before. XXX: PR/32166
- * Note that vnode lock is shared with underlying UVM object.
- */
- if ((flags & PGO_LOCKED) == 0 && pgs) {
- memset(pgs, 0, sizeof(struct vm_pages *) * npages);
- }
+ /* Invoke the pager. The vnode vmobjlock is shared with the UAO. */
KASSERT(vp->v_uobj.vmobjlock == uobj->vmobjlock);
-
error = (*uobj->pgops->pgo_get)(uobj, offset, pgs, &npages, centeridx,
access_type, advice, flags);
-
#if defined(DEBUG)
if (!error && pgs) {
KASSERT(pgs[centeridx] != NULL);
Index: src/sys/uvm/uvm_aobj.c
diff -u src/sys/uvm/uvm_aobj.c:1.141 src/sys/uvm/uvm_aobj.c:1.142
--- src/sys/uvm/uvm_aobj.c:1.141 Sun May 17 19:38:17 2020
+++ src/sys/uvm/uvm_aobj.c Tue May 19 22:22:15 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_aobj.c,v 1.141 2020/05/17 19:38:17 ad Exp $ */
+/* $NetBSD: uvm_aobj.c,v 1.142 2020/05/19 22:22:15 ad Exp $ */
/*
* Copyright (c) 1998 Chuck Silvers, Charles D. Cranor and
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_aobj.c,v 1.141 2020/05/17 19:38:17 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_aobj.c,v 1.142 2020/05/19 22:22:15 ad Exp $");
#ifdef _KERNEL_OPT
#include "opt_uvmhist.h"
@@ -786,14 +786,12 @@ uao_put(struct uvm_object *uobj, voff_t
* 2: page is zero-fill -> allocate a new page and zero it.
* 3: page is swapped out -> fetch the page from swap.
*
- * cases 1 and 2 can be handled with PGO_LOCKED, case 3 cannot.
- * so, if the "center" page hits case 3 (or any page, with PGO_ALLPAGES),
- * then we will need to return EBUSY.
+ * case 1 can be handled with PGO_LOCKED, cases 2 and 3 cannot.
+ * so, if the "center" page hits case 2/3 then we will need to return EBUSY.
*
* => prefer map unlocked (not required)
* => object must be locked! we will _unlock_ it before starting any I/O.
- * => flags: PGO_ALLPAGES: get all of the pages
- * PGO_LOCKED: fault data structures are locked
+ * => flags: PGO_LOCKED: fault data structures are locked
* => NOTE: offset is the offset of pps[0], _NOT_ pps[centeridx]
* => NOTE: caller must check for released pages!!
*/
@@ -805,7 +803,6 @@ uao_get(struct uvm_object *uobj, voff_t
voff_t current_offset;
struct vm_page *ptmp = NULL; /* Quell compiler warning */
int lcv, gotpages, maxpages, swslot, pageidx;
- bool done;
UVMHIST_FUNC("uao_get"); UVMHIST_CALLED(pdhist);
UVMHIST_LOG(pdhist, "aobj=%#jx offset=%jd, flags=%jd",
@@ -841,7 +838,6 @@ uao_get(struct uvm_object *uobj, voff_t
*/
uvm_page_array_init(&a);
- done = true; /* be optimistic */
gotpages = 0; /* # of pages we got so far */
for (lcv = 0; lcv < maxpages; lcv++) {
ptmp = uvm_page_array_fill_and_peek(&a, uobj,
@@ -880,16 +876,9 @@ uao_get(struct uvm_object *uobj, voff_t
* to unlock and do some waiting or I/O.
*/
- if ((flags & PGO_ALLPAGES) != 0) {
- for (int i = 0; i < maxpages; i++) {
- done &= (pps[i] != NULL);
- }
- } else {
- done = (pps[centeridx] != NULL);
- }
UVMHIST_LOG(pdhist, "<- done (done=%jd)", done, 0,0,0);
*npagesp = gotpages;
- return done ? 0 : EBUSY;
+ return pps[centeridx] != NULL ? 0 : EBUSY;
}
/*
@@ -905,17 +894,6 @@ uao_get(struct uvm_object *uobj, voff_t
lcv++, current_offset += PAGE_SIZE) {
/*
- * - skip over pages we've already gotten or don't want
- * - skip over pages we don't _have_ to get
- */
-
- if (pps[lcv] != NULL ||
- (lcv != centeridx && (flags & PGO_ALLPAGES) == 0))
- continue;
-
- pageidx = current_offset >> PAGE_SHIFT;
-
- /*
* we have yet to locate the current page (pps[lcv]). we
* first look for a page that is already at the current offset.
* if we find a page, we check to see if it is busy or
@@ -926,20 +904,23 @@ uao_get(struct uvm_object *uobj, voff_t
* 'break's the following while loop and indicates we are
* ready to move on to the next page in the "lcv" loop above.
*
- * if we exit the while loop with pps[lcv] still set to NULL,
+ * if we exit the while loop with pps[lcv] set to NULL,
* then it means that we allocated a new busy/fake/clean page
* ptmp in the object and we need to do I/O to fill in the data.
*/
/* top of "pps" while loop */
- while (pps[lcv] == NULL) {
+ for (;;) {
/* look for a resident page */
ptmp = uvm_pagelookup(uobj, current_offset);
/* not resident? allocate one now (if we can) */
if (ptmp == NULL) {
-
- ptmp = uao_pagealloc(uobj, current_offset, 0);
+ /* get a zeroed page if not in swap */
+ pageidx = current_offset >> PAGE_SHIFT;
+ swslot = uao_find_swslot(uobj, pageidx);
+ ptmp = uao_pagealloc(uobj, current_offset,
+ swslot == 0 ? UVM_PGA_ZERO : 0);
/* out of RAM? */
if (ptmp == NULL) {
@@ -952,10 +933,11 @@ uao_get(struct uvm_object *uobj, voff_t
}
/*
- * got new page ready for I/O. break pps while
- * loop. pps[lcv] is still NULL.
+ * got new page ready for I/O. break pps for
+ * loop.
*/
+ pps[lcv] = NULL;
break;
}
@@ -982,6 +964,7 @@ uao_get(struct uvm_object *uobj, voff_t
ptmp->flags |= PG_BUSY;
UVM_PAGE_OWN(ptmp, "uao_get2");
pps[lcv] = ptmp;
+ break;
}
/*
@@ -993,24 +976,12 @@ uao_get(struct uvm_object *uobj, voff_t
continue; /* next lcv */
/*
- * we have a "fake/busy/clean" page that we just allocated.
- * do the needed "i/o", either reading from swap or zeroing.
+ * if swslot == 0, page hasn't existed before and is zeroed.
+ * otherwise we have a "fake/busy/clean" page that we just
+ * allocated. do the needed "i/o", reading from swap.
*/
- swslot = uao_find_swslot(uobj, pageidx);
-
- /*
- * just zero the page if there's nothing in swap.
- */
-
- if (swslot == 0) {
-
- /*
- * page hasn't existed before, just zero it.
- */
-
- uvm_pagezero(ptmp);
- } else {
+ if (swslot != 0) {
#if defined(VMSWAP)
int error;
@@ -1049,6 +1020,12 @@ uao_get(struct uvm_object *uobj, voff_t
uvm_pagefree(ptmp);
rw_exit(uobj->vmobjlock);
+ UVMHIST_LOG(pdhist, "<- done (error)",
+ error,lcv,0,0);
+ if (lcv != 0) {
+ uvm_page_unbusy(pps, lcv);
+ }
+ memset(pps, 0, maxpages * sizeof(pps[0]));
return error;
}
#else /* defined(VMSWAP) */
Index: src/sys/uvm/uvm_bio.c
diff -u src/sys/uvm/uvm_bio.c:1.113 src/sys/uvm/uvm_bio.c:1.114
--- src/sys/uvm/uvm_bio.c:1.113 Sun Apr 26 16:16:13 2020
+++ src/sys/uvm/uvm_bio.c Tue May 19 22:22:15 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_bio.c,v 1.113 2020/04/26 16:16:13 thorpej Exp $ */
+/* $NetBSD: uvm_bio.c,v 1.114 2020/05/19 22:22:15 ad Exp $ */
/*
* Copyright (c) 1998 Chuck Silvers.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.113 2020/04/26 16:16:13 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.114 2020/05/19 22:22:15 ad Exp $");
#include "opt_uvmhist.h"
#include "opt_ubc.h"
@@ -823,7 +823,7 @@ ubc_alloc_direct(struct uvm_object *uobj
{
voff_t pgoff;
int error;
- int gpflags = flags | PGO_NOTIMESTAMP | PGO_SYNCIO | PGO_ALLPAGES;
+ int gpflags = flags | PGO_NOTIMESTAMP | PGO_SYNCIO;
int access_type = VM_PROT_READ;
UVMHIST_FUNC("ubc_alloc_direct"); UVMHIST_CALLED(ubchist);
Index: src/sys/uvm/uvm_object.c
diff -u src/sys/uvm/uvm_object.c:1.21 src/sys/uvm/uvm_object.c:1.22
--- src/sys/uvm/uvm_object.c:1.21 Sun Feb 23 15:46:43 2020
+++ src/sys/uvm/uvm_object.c Tue May 19 22:22:15 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_object.c,v 1.21 2020/02/23 15:46:43 ad Exp $ */
+/* $NetBSD: uvm_object.c,v 1.22 2020/05/19 22:22:15 ad Exp $ */
/*
* Copyright (c) 2006, 2010, 2019 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_object.c,v 1.21 2020/02/23 15:46:43 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_object.c,v 1.22 2020/05/19 22:22:15 ad Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@@ -146,7 +146,7 @@ uvm_obj_wirepages(struct uvm_object *uob
memset(pgs, 0, sizeof(pgs));
error = (*uobj->pgops->pgo_get)(uobj, offset, pgs, &npages, 0,
VM_PROT_READ | VM_PROT_WRITE, UVM_ADV_SEQUENTIAL,
- PGO_ALLPAGES | PGO_SYNCIO);
+ PGO_SYNCIO);
if (error)
goto error;
Index: src/sys/uvm/uvm_pager.h
diff -u src/sys/uvm/uvm_pager.h:1.48 src/sys/uvm/uvm_pager.h:1.49
--- src/sys/uvm/uvm_pager.h:1.48 Sun May 17 19:38:17 2020
+++ src/sys/uvm/uvm_pager.h Tue May 19 22:22:15 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_pager.h,v 1.48 2020/05/17 19:38:17 ad Exp $ */
+/* $NetBSD: uvm_pager.h,v 1.49 2020/05/19 22:22:15 ad Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -148,7 +148,7 @@ struct uvm_pagerops {
#define PGO_FREE 0x008 /* free flushed pages */
/* if PGO_FREE is not set then the pages stay where they are. */
-#define PGO_ALLPAGES 0x010 /* flush whole object/get all pages */
+#define PGO_ALLPAGES 0x010 /* flush whole object [put] */
#define PGO_JOURNALLOCKED 0x020 /* journal is already locked [get/put] */
#define PGO_LOCKED 0x040 /* fault data structures are locked [get] */
#define PGO_BUSYFAIL 0x080 /* fail if a page is busy [put] */
Index: src/sys/uvm/uvm_vnode.c
diff -u src/sys/uvm/uvm_vnode.c:1.112 src/sys/uvm/uvm_vnode.c:1.113
--- src/sys/uvm/uvm_vnode.c:1.112 Tue May 19 21:45:57 2020
+++ src/sys/uvm/uvm_vnode.c Tue May 19 22:22:15 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_vnode.c,v 1.112 2020/05/19 21:45:57 ad Exp $ */
+/* $NetBSD: uvm_vnode.c,v 1.113 2020/05/19 22:22:15 ad Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -45,7 +45,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_vnode.c,v 1.112 2020/05/19 21:45:57 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_vnode.c,v 1.113 2020/05/19 22:22:15 ad Exp $");
#ifdef _KERNEL_OPT
#include "opt_uvmhist.h"
@@ -161,8 +161,7 @@ uvn_put(struct uvm_object *uobj, voff_t
*
* => prefer map unlocked (not required)
* => object must be locked! we will _unlock_ it before starting any I/O.
- * => flags: PGO_ALLPAGES: get all of the pages
- * PGO_LOCKED: fault data structures are locked
+ * => flags: PGO_LOCKED: fault data structures are locked
* => NOTE: offset is the offset of pps[0], _NOT_ pps[centeridx]
* => NOTE: caller must check for released pages!!
*/