Subject: Re: kern/15364
To: None <chs@netbsd.org, gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: netbsd-bugs
Date: 08/30/2005 20:32:01
The following reply was made to PR kern/15364; it has been noted by GNATS.

From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
To: chuq@chuq.com
Cc: gnats-bugs@NetBSD.org
Subject: Re: kern/15364
Date: Wed, 31 Aug 2005 05:30:58 +0900

 --NextPart-20050831053047-0408200
 Content-Type: Text/Plain; charset=us-ascii
 
 > > would you like to
 > > implement your bitmap idea?
 > 
 > i will.
 
 here is.
 
 YAMAMOTO Takashi
 
 --NextPart-20050831053047-0408200
 Content-Type: Text/Plain; charset=us-ascii
 Content-Disposition: attachment; filename="a.diff"
 
 Index: ffs_softdep.c
 ===================================================================
 --- ffs_softdep.c	(revision 1330)
 +++ ffs_softdep.c	(working copy)
 @@ -197,6 +197,9 @@ void softdep_pageiodone __P((struct buf 
  void softdep_flush_vnode __P((struct vnode *, daddr_t));
  static void softdep_trackbufs(struct inode *, int, boolean_t);
  
 +#define	PCBP_BITMAP(off, size) \
 +	(((1 << howmany((size), PAGE_SIZE)) - 1) << ((off) >> PAGE_SHIFT))
 +
  /*
   * Exported softdep operations.
   */
 @@ -5804,9 +5807,13 @@ softdep_setup_pagecache(ip, lbn, size)
  		LIST_INSERT_HEAD(&pcbphashhead[PCBPHASH(vp, lbn)], bp, b_hash);
  		LIST_INSERT_HEAD(&ip->i_pcbufhd, bp, b_vnbufs);
  	}
 -	bp->b_bcount = bp->b_resid = size;
 +	bp->b_bcount = size;
 +	KASSERT(size <= PAGE_SIZE * sizeof(bp->b_resid) * CHAR_BIT);
 +	bp->b_resid = PCBP_BITMAP(0, size);
  	UVMHIST_LOG(ubchist, "vp = %p, lbn = %ld, "
 -	    "bp = %p, bcount = resid = %ld", vp, lbn, bp, size);
 +	    "bp = %p, bcount = %ld", vp, lbn, bp, size);
 +	UVMHIST_LOG(ubchist, "b_resid = %ld",
 +	    bp->b_resid, 0, 0, 0);
  	return bp;
  }
  
 @@ -5933,7 +5940,7 @@ softdep_pageiodone1(bp)
  	struct worklist *wk;
  	daddr_t lbn;
  	voff_t off;
 -	long iosize = bp->b_bcount;
 +	int iosize = bp->b_bcount;
  	int size, asize, bshift, bsize;
  	int i;
  	UVMHIST_FUNC("softdep_pageiodone"); UVMHIST_CALLED(ubchist);
 @@ -5946,12 +5953,14 @@ softdep_pageiodone1(bp)
  	for (i = 0; i < npages; i++) {
  		pg = uvm_pageratop((vaddr_t)bp->b_data + (i << PAGE_SHIFT));
  		if (pg == NULL) {
 -			continue;
 +			panic("%s: no page", __func__);
  		}
  
  		for (off = pg->offset;
  		     off < pg->offset + PAGE_SIZE;
  		     off += bsize) {
 +			int pgmask;
 +
  			size = MIN(asize, iosize);
  			iosize -= size;
  			lbn = off >> bshift;
 @@ -5968,14 +5977,14 @@ softdep_pageiodone1(bp)
  			UVMHIST_LOG(ubchist,
  			    "pcbp %p iosize %ld, size %d, asize %d",
  			    pcbp, iosize, size, asize);
 -			pcbp->b_resid -= size;
 -			if (pcbp->b_resid < 0) {
 -				panic("softdep_pageiodone: "
 -				    "resid < 0, vp %p lbn 0x%" PRIx64 " pcbp %p"
 -				    " iosize %ld, size %d, asize %d, bsize %d",
 -				    vp, lbn, pcbp, iosize, size, asize, bsize);
 +			pgmask = PCBP_BITMAP(off & (bsize - 1), size);
 +			if ((~pcbp->b_resid & pgmask) != 0) {
 +				UVMHIST_LOG(ubchist,
 +				    "multiple write resid %lx, pgmask %lx",
 +				    pcbp->b_resid, pgmask, 0, 0);
  			}
 -			if (pcbp->b_resid > 0) {
 +			pcbp->b_resid &= ~pgmask;
 +			if (pcbp->b_resid != 0) {
  				continue;
  			}
  
 Index: ffs_vnops.c
 ===================================================================
 --- ffs_vnops.c	(revision 1276)
 +++ ffs_vnops.c	(working copy)
 @@ -116,7 +116,7 @@ const struct vnodeopv_entry_desc ffs_vno
  	{ &vop_update_desc, ffs_update },		/* update */
  	{ &vop_bwrite_desc, vn_bwrite },		/* bwrite */
  	{ &vop_getpages_desc, ffs_getpages },		/* getpages */
 -	{ &vop_putpages_desc, ffs_putpages },		/* putpages */
 +	{ &vop_putpages_desc, genfs_putpages },		/* putpages */
  	{ NULL, NULL }
  };
  const struct vnodeopv_desc ffs_vnodeop_opv_desc =
 @@ -533,58 +533,6 @@ ffs_getpages(void *v)
  		return EINVAL;
  	}
  	return genfs_getpages(v);
 -}
 -
 -int
 -ffs_putpages(void *v)
 -{
 -	struct vop_putpages_args /* {
 -		struct vnode *a_vp;
 -		voff_t a_offlo;
 -		voff_t a_offhi;
 -		int a_flags;
 -	} */ *ap = v;
 -	struct vnode *vp = ap->a_vp;
 -	struct uvm_object *uobj = &vp->v_uobj;
 -	struct inode *ip = VTOI(vp);
 -	struct fs *fs = ip->i_fs;
 -	struct vm_page *pg;
 -	off_t off;
 -
 -	if (!DOINGSOFTDEP(vp) || (ap->a_flags & PGO_CLEANIT) == 0) {
 -		return genfs_putpages(v);
 -	}
 -
 -	/*
 -	 * for softdep files, force the pages in a block to be written together.
 -	 * if we're the pagedaemon and we would have to wait for other pages,
 -	 * just fail the request.  the pagedaemon will pick a different page.
 -	 */
 -
 -	ap->a_offlo &= ~fs->fs_qbmask;
 -	ap->a_offhi = blkroundup(fs, ap->a_offhi);
 -	if (curproc == uvm.pagedaemon_proc) {
 -		for (off = ap->a_offlo; off < ap->a_offhi; off += PAGE_SIZE) {
 -			pg = uvm_pagelookup(uobj, off);
 -
 -			/*
 -			 * we only have missing pages here because the
 -			 * calculation of offhi above doesn't account for
 -			 * fragments.  so once we see one missing page,
 -			 * the rest should be missing as well, but we'll
 -			 * check for the rest just to be paranoid.
 -			 */
 -
 -			if (pg == NULL) {
 -				continue;
 -			}
 -			if (pg->flags & PG_BUSY) {
 -				simple_unlock(&uobj->vmobjlock);
 -				return EBUSY;
 -			}
 -		}
 -	}
 -	return genfs_putpages(v);
  }
  
  /*
 Index: ffs_extern.h
 ===================================================================
 --- ffs_extern.h	(revision 1266)
 +++ ffs_extern.h	(working copy)
 @@ -153,7 +153,6 @@ int	ffs_write(void *);
  int	ffs_fsync(void *);
  int	ffs_reclaim(void *);
  int	ffs_getpages(void *);
 -int	ffs_putpages(void *);
  void	ffs_gop_size(struct vnode *, off_t, off_t *, int);
  
  #ifdef SYSCTL_SETUP_PROTO
 
 --NextPart-20050831053047-0408200--