Subject: Re: kern/37109: fscow_run + swap on regular file deadlock
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Juergen Hannken-Illjes <hannken@eis.cs.tu-bs.de>
List: netbsd-bugs
Date: 10/12/2007 14:35:02
The following reply was made to PR kern/37109; it has been noted by GNATS.
From: Juergen Hannken-Illjes <hannken@eis.cs.tu-bs.de>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: kern/37109: fscow_run + swap on regular file deadlock
Date: Fri, 12 Oct 2007 16:33:11 +0200
On Thu, Oct 11, 2007 at 05:30:00PM +0000, yamt@mwd.biglobe.ne.jp wrote:
> >Number: 37109
> >Category: kern
> >Synopsis: fscow_run + swap on regular file deadlock
With this diff VOP_STRATEGY() is no longer called from interrupt context.
Yamt, ok to commit?
Index: uvm_swap.c
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_swap.c,v
retrieving revision 1.129
diff -p -u -2 -r1.129 uvm_swap.c
--- uvm_swap.c 29 Jul 2007 13:31:18 -0000 1.129
+++ uvm_swap.c 12 Oct 2007 14:29:45 -0000
@@ -61,4 +61,5 @@ __KERNEL_RCSID(0, "$NetBSD: uvm_swap.c,v
#include <sys/kauth.h>
#include <sys/sysctl.h>
+#include <sys/workqueue.h>
#include <uvm/uvm.h>
@@ -221,4 +222,7 @@ static struct swap_priority swap_priorit
static krwlock_t swap_syscall_lock;
+/* workqueue for swap to regular files */
+static struct workqueue *sw_reg_workqueue;
+
/*
* prototypes
@@ -237,5 +241,6 @@ static void uvm_swap_stats_locked(int, s
static void sw_reg_strategy(struct swapdev *, struct buf *, int);
-static void sw_reg_iodone(struct buf *);
+static void sw_reg_biodone(struct buf *);
+static void sw_reg_iodone(struct work *wk, void *dummy);
static void sw_reg_start(struct swapdev *);
@@ -270,4 +275,8 @@ uvm_swap_init(void)
mutex_init(&uvm_scheduler_mutex, MUTEX_SPIN, IPL_SCHED);
+ if (workqueue_create(&sw_reg_workqueue, "swapiod",
+ sw_reg_iodone, NULL, PRIBIO, IPL_BIO, 0) != 0)
+ panic("uvm_swap_init: workqueue_create failed");
+
if (bdevvp(swapdev, &swapdev_vp))
panic("uvm_swap_init: can't get vnode for swap device");
@@ -1288,5 +1297,5 @@ sw_reg_strategy(struct swapdev *sdp, str
nbp->vb_buf.b_blkno = nbn + btodb(off);
nbp->vb_buf.b_rawblkno = nbp->vb_buf.b_blkno;
- nbp->vb_buf.b_iodone = sw_reg_iodone;
+ nbp->vb_buf.b_iodone = sw_reg_biodone;
nbp->vb_buf.b_vp = vp;
if (vp->v_type == VBLK) {
@@ -1366,4 +1375,13 @@ sw_reg_start(struct swapdev *sdp)
/*
+ * sw_reg_biodone: one of our i/o's has completed
+ */
+static void
+sw_reg_biodone(struct buf *bp)
+{
+ workqueue_enqueue(sw_reg_workqueue, &bp->b_work, NULL);
+}
+
+/*
* sw_reg_iodone: one of our i/o's has completed and needs post-i/o cleanup
*
@@ -1371,11 +1389,12 @@ sw_reg_start(struct swapdev *sdp)
*/
static void
-sw_reg_iodone(struct buf *bp)
+sw_reg_iodone(struct work *wk, void *dummy)
{
- struct vndbuf *vbp = (struct vndbuf *) bp;
+ struct vndbuf *vbp = (void *)wk;
struct vndxfer *vnx = vbp->vb_xfer;
struct buf *pbp = vnx->vx_bp; /* parent buffer */
struct swapdev *sdp = vnx->vx_sdp;
int s, resid, error;
+ KASSERT(&vbp->vb_buf.b_work == wk);
UVMHIST_FUNC("sw_reg_iodone"); UVMHIST_CALLED(pdhist);
--
Juergen Hannken-Illjes - hannken@eis.cs.tu-bs.de - TU Braunschweig (Germany)