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)