summaryrefslogtreecommitdiff
path: root/sys/miscfs
diff options
context:
space:
mode:
authorhannken <hannken@NetBSD.org>2010-11-09 16:31:48 +0000
committerhannken <hannken@NetBSD.org>2010-11-09 16:31:48 +0000
commit1c9818e8f4dff965e39844229fa87f2d9367e1eb (patch)
tree1bdbe0dc0ce6ccc663503660f85511be97b855b7 /sys/miscfs
parent897bf1dab04eb6fc436829d25a0232cb65b0888d (diff)
Genfs_getpages(): Break a deadlock where one thread runs VOP_GETPAGES(),
has busy pages and wants the wapbl lock as reader from wapbl_begin(), another thread has the wapbl lock as reader and waits for a page from the first thread. Now a third thread calls wapbl_flush() and wants the wapbl lock as writer. Move the wapbl_begin() up to a point where genfs_getpages() has no busy pages yet.
Diffstat (limited to 'sys/miscfs')
-rw-r--r--sys/miscfs/genfs/genfs_io.c45
1 files changed, 23 insertions, 22 deletions
diff --git a/sys/miscfs/genfs/genfs_io.c b/sys/miscfs/genfs/genfs_io.c
index 576dca37286..e9f9b2039b4 100644
--- a/sys/miscfs/genfs/genfs_io.c
+++ b/sys/miscfs/genfs/genfs_io.c
@@ -1,4 +1,4 @@
-/* $NetBSD: genfs_io.c,v 1.41 2010/11/03 04:32:50 uebayasi Exp $ */
+/* $NetBSD: genfs_io.c,v 1.42 2010/11/09 16:31:48 hannken Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.41 2010/11/03 04:32:50 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.42 2010/11/09 16:31:48 hannken Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -129,10 +129,11 @@ genfs_getpages(void *v)
kauth_cred_t const cred = curlwp->l_cred; /* XXXUBC curlwp */
const bool async = (flags & PGO_SYNCIO) == 0;
const bool memwrite = (ap->a_access_type & VM_PROT_WRITE) != 0;
- 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;
+ const bool need_wapbl = blockalloc && vp->v_mount->mnt_wapbl;
+ bool has_trans_wapbl = false;
UVMHIST_FUNC("genfs_getpages"); UVMHIST_CALLED(ubchist);
UVMHIST_LOG(ubchist, "vp %p off 0x%x/%x count %d",
@@ -294,9 +295,20 @@ startover:
UVMHIST_LOG(ubchist, "ridx %d npages %d startoff %ld endoff %ld",
ridx, npages, startoffset, endoffset);
- if (!has_trans) {
+ if (!has_trans_wapbl) {
fstrans_start(vp->v_mount, FSTRANS_SHARED);
- has_trans = true;
+ /*
+ * XXX: This assumes that we come here only via
+ * the mmio path
+ */
+ if (need_wapbl) {
+ error = WAPBL_BEGIN(vp->v_mount);
+ if (error) {
+ fstrans_done(vp->v_mount);
+ goto out_err_free;
+ }
+ }
+ has_trans_wapbl = true;
}
/*
@@ -621,22 +633,8 @@ loopdone:
*/
if (!error && sawhole && blockalloc) {
- /*
- * XXX: This assumes that we come here only via
- * the mmio path
- */
- if (vp->v_mount->mnt_wapbl) {
- error = WAPBL_BEGIN(vp->v_mount);
- }
-
- if (!error) {
- error = GOP_ALLOC(vp, startoffset,
- npages << PAGE_SHIFT, 0, cred);
- if (vp->v_mount->mnt_wapbl) {
- WAPBL_END(vp->v_mount);
- }
- }
-
+ error = GOP_ALLOC(vp, startoffset,
+ npages << PAGE_SHIFT, 0, cred);
UVMHIST_LOG(ubchist, "gop_alloc off 0x%x/0x%x -> %d",
startoffset, npages << PAGE_SHIFT, error,0);
if (!error) {
@@ -738,8 +736,11 @@ out_err_free:
if (pgs != NULL && pgs != pgs_onstack)
kmem_free(pgs, pgs_size);
out_err:
- if (has_trans)
+ if (has_trans_wapbl) {
+ if (need_wapbl)
+ WAPBL_END(vp->v_mount);
fstrans_done(vp->v_mount);
+ }
return error;
}