Module Name:    src
Committed By:   chs
Date:           Wed Sep  1 16:56:20 UTC 2010

Modified Files:
        src/sys/miscfs/genfs: genfs_io.c genfs_node.h genfs_vnops.c
        src/sys/ufs/ufs: ufs_inode.c
        src/sys/uvm: uvm_pager.h

Log Message:
replace the earlier workaround for PR 40389 with a better fix.
the earlier change caused data corruption by freeing pages
without invaliding their mappings.  instead of the trylock/retry,
just take the genfs-node lock before calling VOP_GETPAGES()
and pass a new flag to tell it that we're already holding this lock.


To generate a diff of this commit:
cvs rdiff -u -r1.39 -r1.40 src/sys/miscfs/genfs/genfs_io.c
cvs rdiff -u -r1.19 -r1.20 src/sys/miscfs/genfs/genfs_node.h
cvs rdiff -u -r1.182 -r1.183 src/sys/miscfs/genfs/genfs_vnops.c
cvs rdiff -u -r1.82 -r1.83 src/sys/ufs/ufs/ufs_inode.c
cvs rdiff -u -r1.38 -r1.39 src/sys/uvm/uvm_pager.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/miscfs/genfs/genfs_io.c
diff -u src/sys/miscfs/genfs/genfs_io.c:1.39 src/sys/miscfs/genfs/genfs_io.c:1.40
--- src/sys/miscfs/genfs/genfs_io.c:1.39	Thu Aug 19 02:10:02 2010
+++ src/sys/miscfs/genfs/genfs_io.c	Wed Sep  1 16:56:19 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: genfs_io.c,v 1.39 2010/08/19 02:10:02 pooka Exp $	*/
+/*	$NetBSD: genfs_io.c,v 1.40 2010/09/01 16:56:19 chs Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.39 2010/08/19 02:10:02 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.40 2010/09/01 16:56:19 chs Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -125,7 +125,6 @@
 	int i, error, npages;
 	const int flags = ap->a_flags;
 	struct vnode * const vp = ap->a_vp;
-	struct genfs_node * const gp = VTOG(vp);
 	struct uvm_object * const uobj = &vp->v_uobj;
 	kauth_cred_t const cred = curlwp->l_cred;		/* XXXUBC curlwp */
 	const bool async = (flags & PGO_SYNCIO) == 0;
@@ -133,6 +132,7 @@
 	bool has_trans = false;
 	const bool overwrite = (flags & PGO_OVERWRITE) != 0;
 	const bool blockalloc = memwrite && (flags & PGO_NOBLOCKALLOC) == 0;
+	const bool glocked = (flags & PGO_GLOCKHELD) != 0;
 	UVMHIST_FUNC("genfs_getpages"); UVMHIST_CALLED(ubchist);
 
 	UVMHIST_LOG(ubchist, "vp %p off 0x%x/%x count %d",
@@ -211,6 +211,7 @@
 		int nfound;
 		struct vm_page *pg;
 
+		KASSERT(!glocked);
 		npages = *ap->a_count;
 #if defined(DEBUG)
 		for (i = 0; i < npages; i++) {
@@ -303,14 +304,19 @@
 	 * check if our idea of v_size is still valid.
 	 */
 
-	if (blockalloc) {
-		rw_enter(&gp->g_glock, RW_WRITER);
-	} else {
-		rw_enter(&gp->g_glock, RW_READER);
+	KASSERT(!glocked || genfs_node_wrlocked(vp));
+	if (!glocked) {
+		if (blockalloc) {
+			genfs_node_wrlock(vp);
+		} else {
+			genfs_node_rdlock(vp);
+		}
 	}
 	mutex_enter(&uobj->vmobjlock);
 	if (vp->v_size < origvsize) {
-		genfs_node_unlock(vp);
+		if (!glocked) {
+			genfs_node_unlock(vp);
+		}
 		if (pgs != pgs_onstack)
 			kmem_free(pgs, pgs_size);
 		goto startover;
@@ -318,7 +324,9 @@
 
 	if (uvn_findpages(uobj, origoffset, &npages, &pgs[ridx],
 	    async ? UFP_NOWAIT : UFP_ALL) != orignmempages) {
-		genfs_node_unlock(vp);
+		if (!glocked) {
+			genfs_node_unlock(vp);
+		}
 		KASSERT(async != 0);
 		genfs_rel_pages(&pgs[ridx], orignmempages);
 		mutex_exit(&uobj->vmobjlock);
@@ -339,7 +347,9 @@
 		}
 	}
 	if (i == npages) {
-		genfs_node_unlock(vp);
+		if (!glocked) {
+			genfs_node_unlock(vp);
+		}
 		UVMHIST_LOG(ubchist, "returning cached pages", 0,0,0,0);
 		npages += ridx;
 		goto out;
@@ -350,7 +360,9 @@
 	 */
 
 	if (overwrite) {
-		genfs_node_unlock(vp);
+		if (!glocked) {
+			genfs_node_unlock(vp);
+		}
 		UVMHIST_LOG(ubchist, "PGO_OVERWRITE",0,0,0,0);
 
 		for (i = 0; i < npages; i++) {
@@ -386,7 +398,9 @@
 		npgs = npages;
 		if (uvn_findpages(uobj, startoffset, &npgs, pgs,
 		    async ? UFP_NOWAIT : UFP_ALL) != npages) {
-			genfs_node_unlock(vp);
+			if (!glocked) {
+				genfs_node_unlock(vp);
+			}
 			KASSERT(async != 0);
 			genfs_rel_pages(pgs, npages);
 			mutex_exit(&uobj->vmobjlock);
@@ -584,7 +598,9 @@
 	nestiobuf_done(mbp, skipbytes, error);
 	if (async) {
 		UVMHIST_LOG(ubchist, "returning 0 (async)",0,0,0,0);
-		genfs_node_unlock(vp);
+		if (!glocked) {
+			genfs_node_unlock(vp);
+		}
 		error = 0;
 		goto out_err_free;
 	}
@@ -635,7 +651,9 @@
 			}
 		}
 	}
-	genfs_node_unlock(vp);
+	if (!glocked) {
+		genfs_node_unlock(vp);
+	}
 
 	putiobuf(mbp);
     }

Index: src/sys/miscfs/genfs/genfs_node.h
diff -u src/sys/miscfs/genfs/genfs_node.h:1.19 src/sys/miscfs/genfs/genfs_node.h:1.20
--- src/sys/miscfs/genfs/genfs_node.h:1.19	Wed Jan 27 15:52:31 2010
+++ src/sys/miscfs/genfs/genfs_node.h	Wed Sep  1 16:56:19 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: genfs_node.h,v 1.19 2010/01/27 15:52:31 uebayasi Exp $ */
+/* $NetBSD: genfs_node.h,v 1.20 2010/09/01 16:56:19 chs Exp $ */
 
 /*
  * Copyright (c) 2001 Chuck Silvers.
@@ -93,5 +93,6 @@
 void	genfs_node_rdlock(struct vnode *);
 int	genfs_node_rdtrylock(struct vnode *);
 void	genfs_node_unlock(struct vnode *);
+int	genfs_node_wrlocked(struct vnode *);
 
 #endif	/* _MISCFS_GENFS_GENFS_NODE_H_ */

Index: src/sys/miscfs/genfs/genfs_vnops.c
diff -u src/sys/miscfs/genfs/genfs_vnops.c:1.182 src/sys/miscfs/genfs/genfs_vnops.c:1.183
--- src/sys/miscfs/genfs/genfs_vnops.c:1.182	Thu Jul  1 13:00:56 2010
+++ src/sys/miscfs/genfs/genfs_vnops.c	Wed Sep  1 16:56:19 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: genfs_vnops.c,v 1.182 2010/07/01 13:00:56 hannken Exp $	*/
+/*	$NetBSD: genfs_vnops.c,v 1.183 2010/09/01 16:56:19 chs Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -57,7 +57,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.182 2010/07/01 13:00:56 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.183 2010/09/01 16:56:19 chs Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -551,6 +551,14 @@
 	rw_exit(&gp->g_glock);
 }
 
+int
+genfs_node_wrlocked(struct vnode *vp)
+{
+	struct genfs_node *gp = VTOG(vp);
+
+	return rw_write_held(&gp->g_glock);
+}
+
 /*
  * Do the usual access checking.
  * file_mode, uid and gid are from the vnode in question,

Index: src/sys/ufs/ufs/ufs_inode.c
diff -u src/sys/ufs/ufs/ufs_inode.c:1.82 src/sys/ufs/ufs/ufs_inode.c:1.83
--- src/sys/ufs/ufs/ufs_inode.c:1.82	Wed Jul 28 11:03:48 2010
+++ src/sys/ufs/ufs/ufs_inode.c	Wed Sep  1 16:56:19 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_inode.c,v 1.82 2010/07/28 11:03:48 hannken Exp $	*/
+/*	$NetBSD: ufs_inode.c,v 1.83 2010/09/01 16:56:19 chs Exp $	*/
 
 /*
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.82 2010/07/28 11:03:48 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.83 2010/09/01 16:56:19 chs Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -264,11 +264,11 @@
 	off -= delta;
 	len += delta;
 
- retry:
+	genfs_node_wrlock(vp);
 	mutex_enter(&uobj->vmobjlock);
 	error = VOP_GETPAGES(vp, pagestart, pgs, &npages, 0,
-	    VM_PROT_WRITE, 0,
-	    PGO_SYNCIO|PGO_PASTEOF|PGO_NOBLOCKALLOC|PGO_NOTIMESTAMP);
+	    VM_PROT_WRITE, 0, PGO_SYNCIO | PGO_PASTEOF | PGO_NOBLOCKALLOC |
+	    PGO_NOTIMESTAMP | PGO_GLOCKHELD);
 	if (error) {
 		goto out;
 	}
@@ -287,25 +287,6 @@
 	 * now allocate the range.
 	 */
 
-	/*
-	 * XXX: Hack around deadlock with pagebusy and genfs node lock.
-	 *      This should be properly fixed.  PR kern/40389
-	 */
-	{
-	struct genfs_node *gp = VTOG(vp); /* XXX */
-
-	if (!rw_tryenter(&gp->g_glock, RW_WRITER)) {
-		mutex_enter(&uobj->vmobjlock);
-		for (i = 0; i < npages; i++)
-			pgs[i]->flags |= PG_RELEASED | PG_CLEAN;
-		mutex_enter(&uvm_pageqlock);
-		uvm_page_unbusy(pgs, npages);
-		mutex_exit(&uvm_pageqlock);
-		mutex_exit(&uobj->vmobjlock);
-		kpause("uballo", false, 1, NULL);
-		goto retry;
-	}}
-
 	error = GOP_ALLOC(vp, off, len, flags, cred);
 	genfs_node_unlock(vp);
 

Index: src/sys/uvm/uvm_pager.h
diff -u src/sys/uvm/uvm_pager.h:1.38 src/sys/uvm/uvm_pager.h:1.39
--- src/sys/uvm/uvm_pager.h:1.38	Fri Aug 22 10:48:22 2008
+++ src/sys/uvm/uvm_pager.h	Wed Sep  1 16:56:19 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_pager.h,v 1.38 2008/08/22 10:48:22 hannken Exp $	*/
+/*	$NetBSD: uvm_pager.h,v 1.39 2010/09/01 16:56:19 chs Exp $	*/
 
 /*
  *
@@ -164,6 +164,7 @@
 #define PGO_NOBLOCKALLOC 0x800	/* backing block allocation is not needed */
 #define PGO_NOTIMESTAMP 0x1000	/* don't mark object accessed/modified */
 #define PGO_RECLAIM	0x2000	/* object is being reclaimed */
+#define PGO_GLOCKHELD	0x4000	/* genfs_node's lock is already held */
 
 /* page we are not interested in getting */
 #define PGO_DONTCARE ((struct vm_page *) -1L)	/* [get only] */

Reply via email to