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--