Module Name:    src
Committed By:   rin
Date:           Sun Oct 18 08:52:15 UTC 2020

Modified Files:
        src/sys/uvm: uvm_bio.c

Log Message:
PR kern/55658

Revert rev 1.122:
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/uvm/uvm_bio.c#rev1.122

If this commit is applied to NFS client, changes to files in client
side are sometimes invisible in server side, which results in file
corruption.

Demonstrated by test code provided by Anthony Mallet:
https://mail-index.netbsd.org/current-users/2020/10/17/msg039708.html

Whether the test case above passes or not depends on architectures
and size of NFS I/O specified by -r and -w options of mount_nfs(8)
(the default size is 32KB for x86 and 8KB for other archs).

Whereas it fails on amd64 and i386 with the default size, it passes
on other archs (aarch64, arm, alpha, m68k, and powerpc at least) with
their default. On most ports, it fails with some I/O sizes.

However, the condition for failure is still unclear; whereas it fails
with 2KB I/O size on amiga (m68k, 8KB page), it passes with same I/O
size on alpha (8KB page). It may depends on some VM parameters or
details in pmap implementation, or some race conditions are involved.

Great thanks to Anthony Mallet for providing the test code, and sorry
everyone for breakage.


To generate a diff of this commit:
cvs rdiff -u -r1.122 -r1.123 src/sys/uvm/uvm_bio.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_bio.c
diff -u src/sys/uvm/uvm_bio.c:1.122 src/sys/uvm/uvm_bio.c:1.123
--- src/sys/uvm/uvm_bio.c:1.122	Mon Oct  5 04:48:23 2020
+++ src/sys/uvm/uvm_bio.c	Sun Oct 18 08:52:15 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_bio.c,v 1.122 2020/10/05 04:48:23 rin Exp $	*/
+/*	$NetBSD: uvm_bio.c,v 1.123 2020/10/18 08:52:15 rin Exp $	*/
 
 /*
  * Copyright (c) 1998 Chuck Silvers.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.122 2020/10/05 04:48:23 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.123 2020/10/18 08:52:15 rin Exp $");
 
 #include "opt_uvmhist.h"
 #include "opt_ubc.h"
@@ -235,7 +235,9 @@ static inline int
 ubc_fault_page(const struct uvm_faultinfo *ufi, const struct ubc_map *umap,
     struct vm_page *pg, vm_prot_t prot, vm_prot_t access_type, vaddr_t va)
 {
+	vm_prot_t mask;
 	int error;
+	bool rdonly;
 
 	KASSERT(rw_write_held(pg->uobject->vmobjlock));
 
@@ -278,11 +280,11 @@ ubc_fault_page(const struct uvm_faultinf
 	    pg->offset < umap->writeoff ||
 	    pg->offset + PAGE_SIZE > umap->writeoff + umap->writelen);
 
-	KASSERT((access_type & VM_PROT_WRITE) == 0 ||
-	    uvm_pagegetdirty(pg) != UVM_PAGE_STATUS_CLEAN);
+	rdonly = uvm_pagereadonly_p(pg);
+	mask = rdonly ? ~VM_PROT_WRITE : VM_PROT_ALL;
 
 	error = pmap_enter(ufi->orig_map->pmap, va, VM_PAGE_TO_PHYS(pg),
-	    prot, PMAP_CANFAIL | access_type);
+	    prot & mask, PMAP_CANFAIL | (access_type & mask));
 
 	uvm_pagelock(pg);
 	uvm_pageactivate(pg);

Reply via email to