Module Name: src
Committed By: bouyer
Date: Tue Sep 7 19:33:44 UTC 2010
Modified Files:
src/sys/miscfs/genfs [netbsd-5-0]: genfs_io.c genfs_node.h
genfs_vnops.c
src/sys/ufs/ufs [netbsd-5-0]: ufs_inode.c
src/sys/uvm [netbsd-5-0]: uvm_pager.h
Log Message:
Pull up following revision(s) (requested by chs in ticket #1448):
sys/uvm/uvm_pager.h: revision 1.39 via patch
sys/miscfs/genfs/genfs_vnops.c: revision 1.183 via patch
sys/ufs/ufs/ufs_inode.c: revision 1.83 via patch
sys/miscfs/genfs/genfs_io.c: revision 1.40 via patch
sys/miscfs/genfs/genfs_node.h: revision 1.20 via patch
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.13.4.2 -r1.13.4.2.2.1 src/sys/miscfs/genfs/genfs_io.c
cvs rdiff -u -r1.17 -r1.17.14.1 src/sys/miscfs/genfs/genfs_node.h
cvs rdiff -u -r1.167 -r1.167.16.1 src/sys/miscfs/genfs/genfs_vnops.c
cvs rdiff -u -r1.76.4.1 -r1.76.4.1.2.1 src/sys/ufs/ufs/ufs_inode.c
cvs rdiff -u -r1.38 -r1.38.10.1 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.13.4.2 src/sys/miscfs/genfs/genfs_io.c:1.13.4.2.2.1
--- src/sys/miscfs/genfs/genfs_io.c:1.13.4.2 Sat Apr 4 18:14:50 2009
+++ src/sys/miscfs/genfs/genfs_io.c Tue Sep 7 19:33:44 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: genfs_io.c,v 1.13.4.2 2009/04/04 18:14:50 snj Exp $ */
+/* $NetBSD: genfs_io.c,v 1.13.4.2.2.1 2010/09/07 19:33:44 bouyer Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.13.4.2 2009/04/04 18:14:50 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.13.4.2.2.1 2010/09/07 19:33:44 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -126,6 +126,7 @@
bool has_trans = false;
const bool overwrite = (flags & PGO_OVERWRITE) != 0;
const bool blockalloc = write && (flags & PGO_NOBLOCKALLOC) == 0;
+ const bool glocked = (flags & PGO_GLOCKHELD) != 0;
voff_t origvsize;
UVMHIST_FUNC("genfs_getpages"); UVMHIST_CALLED(ubchist);
@@ -214,6 +215,7 @@
if (flags & PGO_LOCKED) {
int nfound;
+ KASSERT(!glocked);
npages = *ap->a_count;
#if defined(DEBUG)
for (i = 0; i < npages; i++) {
@@ -228,7 +230,7 @@
error = EBUSY;
goto out_err;
}
- if (!rw_tryenter(&gp->g_glock, RW_READER)) {
+ if (!genfs_node_rdtrylock(vp)) {
genfs_rel_pages(ap->a_m, npages);
/*
@@ -243,7 +245,7 @@
}
}
} else {
- rw_exit(&gp->g_glock);
+ genfs_node_unlock(vp);
}
error = (ap->a_m[ap->a_centeridx] == NULL ? EBUSY : 0);
goto out_err;
@@ -302,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) {
- rw_exit(&gp->g_glock);
+ if (!glocked) {
+ genfs_node_unlock(vp);
+ }
if (pgs != pgs_onstack)
kmem_free(pgs, pgs_size);
goto startover;
@@ -317,7 +324,9 @@
if (uvn_findpages(uobj, origoffset, &npages, &pgs[ridx],
async ? UFP_NOWAIT : UFP_ALL) != orignpages) {
- rw_exit(&gp->g_glock);
+ if (!glocked) {
+ genfs_node_unlock(vp);
+ }
KASSERT(async != 0);
genfs_rel_pages(&pgs[ridx], orignpages);
mutex_exit(&uobj->vmobjlock);
@@ -338,7 +347,9 @@
}
}
if (i == npages) {
- rw_exit(&gp->g_glock);
+ if (!glocked) {
+ genfs_node_unlock(vp);
+ }
UVMHIST_LOG(ubchist, "returning cached pages", 0,0,0,0);
npages += ridx;
goto out;
@@ -349,7 +360,9 @@
*/
if (overwrite) {
- rw_exit(&gp->g_glock);
+ if (!glocked) {
+ genfs_node_unlock(vp);
+ }
UVMHIST_LOG(ubchist, "PGO_OVERWRITE",0,0,0,0);
for (i = 0; i < npages; i++) {
@@ -384,7 +397,9 @@
npgs = npages;
if (uvn_findpages(uobj, startoffset, &npgs, pgs,
async ? UFP_NOWAIT : UFP_ALL) != npages) {
- rw_exit(&gp->g_glock);
+ if (!glocked) {
+ genfs_node_unlock(vp);
+ }
KASSERT(async != 0);
genfs_rel_pages(pgs, npages);
mutex_exit(&uobj->vmobjlock);
@@ -565,7 +580,9 @@
nestiobuf_done(mbp, skipbytes, error);
if (async) {
UVMHIST_LOG(ubchist, "returning 0 (async)",0,0,0,0);
- rw_exit(&gp->g_glock);
+ if (!glocked) {
+ genfs_node_unlock(vp);
+ }
error = 0;
goto out_err;
}
@@ -613,7 +630,9 @@
}
}
}
- rw_exit(&gp->g_glock);
+ if (!glocked) {
+ genfs_node_unlock(vp);
+ }
mutex_enter(&uobj->vmobjlock);
/*
Index: src/sys/miscfs/genfs/genfs_node.h
diff -u src/sys/miscfs/genfs/genfs_node.h:1.17 src/sys/miscfs/genfs/genfs_node.h:1.17.14.1
--- src/sys/miscfs/genfs/genfs_node.h:1.17 Wed May 14 16:49:47 2008
+++ src/sys/miscfs/genfs/genfs_node.h Tue Sep 7 19:33:44 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: genfs_node.h,v 1.17 2008/05/14 16:49:47 reinoud Exp $ */
+/* $NetBSD: genfs_node.h,v 1.17.14.1 2010/09/07 19:33:44 bouyer Exp $ */
/*
* Copyright (c) 2001 Chuck Silvers.
@@ -91,6 +91,8 @@
void genfs_node_wrlock(struct vnode *);
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.167 src/sys/miscfs/genfs/genfs_vnops.c:1.167.16.1
--- src/sys/miscfs/genfs/genfs_vnops.c:1.167 Mon Apr 28 20:24:08 2008
+++ src/sys/miscfs/genfs/genfs_vnops.c Tue Sep 7 19:33:44 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: genfs_vnops.c,v 1.167 2008/04/28 20:24:08 martin Exp $ */
+/* $NetBSD: genfs_vnops.c,v 1.167.16.1 2010/09/07 19:33:44 bouyer 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.167 2008/04/28 20:24:08 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.167.16.1 2010/09/07 19:33:44 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -493,6 +493,14 @@
rw_enter(&gp->g_glock, RW_READER);
}
+int
+genfs_node_rdtrylock(struct vnode *vp)
+{
+ struct genfs_node *gp = VTOG(vp);
+
+ return rw_tryenter(&gp->g_glock, RW_READER);
+}
+
void
genfs_node_unlock(struct vnode *vp)
{
@@ -500,3 +508,11 @@
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);
+}
Index: src/sys/ufs/ufs/ufs_inode.c
diff -u src/sys/ufs/ufs/ufs_inode.c:1.76.4.1 src/sys/ufs/ufs/ufs_inode.c:1.76.4.1.2.1
--- src/sys/ufs/ufs/ufs_inode.c:1.76.4.1 Sun Feb 8 19:08:23 2009
+++ src/sys/ufs/ufs/ufs_inode.c Tue Sep 7 19:33:44 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_inode.c,v 1.76.4.1 2009/02/08 19:08:23 snj Exp $ */
+/* $NetBSD: ufs_inode.c,v 1.76.4.1.2.1 2010/09/07 19:33:44 bouyer Exp $ */
/*
* Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.76.4.1 2009/02/08 19:08:23 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.76.4.1.2.1 2010/09/07 19:33:44 bouyer Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -275,11 +275,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;
}
@@ -298,25 +298,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.38.10.1
--- src/sys/uvm/uvm_pager.h:1.38 Fri Aug 22 10:48:22 2008
+++ src/sys/uvm/uvm_pager.h Tue Sep 7 19:33:44 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.38.10.1 2010/09/07 19:33:44 bouyer 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] */