Allocate buf using getiobuf() instead of abusing the stack.

This commit is contained in:
pooka 2007-11-04 19:37:29 +00:00
parent 08ac8063af
commit 0be31eefc7
1 changed files with 69 additions and 33 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: genfs_io.c,v 1.2 2007/10/31 15:57:20 pooka Exp $ */ /* $NetBSD: genfs_io.c,v 1.3 2007/11/04 19:37:29 pooka Exp $ */
/* /*
* Copyright (c) 2007 Antti Kantee. All Rights Reserved. * Copyright (c) 2007 Antti Kantee. All Rights Reserved.
@ -57,7 +57,6 @@ genfs_getpages(void *v)
int a_flags; int a_flags;
} */ *ap = v; } */ *ap = v;
struct vnode *vp = ap->a_vp; struct vnode *vp = ap->a_vp;
struct buf buf;
struct vm_page *pg; struct vm_page *pg;
voff_t curoff, endoff; voff_t curoff, endoff;
size_t remain, bufoff, xfersize; size_t remain, bufoff, xfersize;
@ -65,8 +64,15 @@ genfs_getpages(void *v)
int bshift = vp->v_mount->mnt_fs_bshift; int bshift = vp->v_mount->mnt_fs_bshift;
int bsize = 1<<bshift; int bsize = 1<<bshift;
int count = *ap->a_count; int count = *ap->a_count;
int async;
int i, error; int i, error;
/*
* Ignore async for now, the structure of this routine
* doesn't exactly allow for it ...
*/
async = 0;
if (ap->a_centeridx != 0) if (ap->a_centeridx != 0)
panic("%s: centeridx != not supported", __func__); panic("%s: centeridx != not supported", __func__);
@ -104,6 +110,7 @@ genfs_getpages(void *v)
tmpbuf = rumpuser_malloc(round_page(remain), 0); tmpbuf = rumpuser_malloc(round_page(remain), 0);
memset(tmpbuf, 0, round_page(remain)); memset(tmpbuf, 0, round_page(remain));
for (bufoff = 0; remain; remain -= xfersize, bufoff+=xfersize) { for (bufoff = 0; remain; remain -= xfersize, bufoff+=xfersize) {
struct buf *bp;
struct vnode *devvp; struct vnode *devvp;
daddr_t lbn, bn; daddr_t lbn, bn;
int run; int run;
@ -124,17 +131,27 @@ genfs_getpages(void *v)
continue; continue;
} }
memset(&buf, 0, sizeof(buf)); bp = getiobuf();
buf.b_data = tmpbuf + bufoff;
buf.b_bcount = xfersize;
buf.b_blkno = bn;
buf.b_lblkno = 0;
buf.b_flags = B_READ | B_BUSY;
buf.b_vp = vp;
VOP_STRATEGY(devvp, &buf); bp->b_data = tmpbuf + bufoff;
if (buf.b_error) bp->b_bcount = xfersize;
bp->b_blkno = bn;
bp->b_lblkno = 0;
bp->b_flags = B_READ | B_BUSY;
if (async) {
bp->b_flags |= B_ASYNC | B_CALL;
bp->b_iodone = uvm_aio_biodone;
}
bp->b_vp = vp;
VOP_STRATEGY(devvp, bp);
if (bp->b_error)
panic("%s: VOP_STRATEGY, lazy bum", __func__); panic("%s: VOP_STRATEGY, lazy bum", __func__);
if (!async)
putiobuf(bp);
} }
/* skip to beginning of pages we're interested in */ /* skip to beginning of pages we're interested in */
@ -189,12 +206,20 @@ genfs_putpages(void *v)
ap->a_flags, NULL); ap->a_flags, NULL);
} }
/*
* This is a slightly strangely structured routine. It always puts
* all the pages for a vnode. It starts by releasing pages which
* are clean and simultaneously looks up the smallest offset for a
* dirty page beloning to the object. If there is no smallest offset,
* all pages have been cleaned. Otherwise, it finds a contiguous range
* of dirty pages starting from the smallest offset and writes them out.
* After this the scan is restarted.
*/
int int
genfs_do_putpages(struct vnode *vp, off_t startoff, off_t endoff, int flags, genfs_do_putpages(struct vnode *vp, off_t startoff, off_t endoff, int flags,
struct vm_page **busypg) struct vm_page **busypg)
{ {
char databuf[MAXPHYS]; char databuf[MAXPHYS];
struct buf buf;
struct uvm_object *uobj = &vp->v_uobj; struct uvm_object *uobj = &vp->v_uobj;
struct vm_page *pg, *pg_next; struct vm_page *pg, *pg_next;
voff_t smallest; voff_t smallest;
@ -203,15 +228,21 @@ genfs_do_putpages(struct vnode *vp, off_t startoff, off_t endoff, int flags,
size_t xfersize; size_t xfersize;
int bshift = vp->v_mount->mnt_fs_bshift; int bshift = vp->v_mount->mnt_fs_bshift;
int bsize = 1 << bshift; int bsize = 1 << bshift;
#if 0
int async = (flags & PGO_SYNCIO) == 0; int async = (flags & PGO_SYNCIO) == 0;
#else
int async = 0;
#endif
restart: restart:
/* check if all pages are clean */ /* check if all pages are clean */
smallest = -1; smallest = -1;
simple_lock(&uobj->vmobjlock);
for (pg = TAILQ_FIRST(&uobj->memq); pg; pg = pg_next) { for (pg = TAILQ_FIRST(&uobj->memq); pg; pg = pg_next) {
pg_next = TAILQ_NEXT(pg, listq); pg_next = TAILQ_NEXT(pg, listq);
if (pg->flags & PG_CLEAN) { if (pg->flags & PG_CLEAN) {
rumpvm_freepage(pg); rumpvm_freepage(pg);
simple_lock(&uobj->vmobjlock);
continue; continue;
} }
@ -222,8 +253,10 @@ genfs_do_putpages(struct vnode *vp, off_t startoff, off_t endoff, int flags,
/* all done? */ /* all done? */
if (TAILQ_EMPTY(&uobj->memq)) { if (TAILQ_EMPTY(&uobj->memq)) {
vp->v_iflag &= ~VI_ONWORKLST; vp->v_iflag &= ~VI_ONWORKLST;
simple_unlock(&uobj->vmobjlock);
return 0; return 0;
} }
simple_unlock(&uobj->vmobjlock);
GOP_SIZE(vp, vp->v_writesize, &eof, 0); GOP_SIZE(vp, vp->v_writesize, &eof, 0);
@ -246,12 +279,11 @@ genfs_do_putpages(struct vnode *vp, off_t startoff, off_t endoff, int flags,
/* then we write */ /* then we write */
for (bufoff = 0; bufoff < MIN(curoff-smallest,eof); bufoff+=xfersize) { for (bufoff = 0; bufoff < MIN(curoff-smallest,eof); bufoff+=xfersize) {
struct buf *bp;
struct vnode *devvp; struct vnode *devvp;
daddr_t bn, lbn; daddr_t bn, lbn;
int run, error; int run, error;
memset(&buf, 0, sizeof(buf));
lbn = (smallest + bufoff) >> bshift; lbn = (smallest + bufoff) >> bshift;
error = VOP_BMAP(vp, lbn, &devvp, &bn, &run); error = VOP_BMAP(vp, lbn, &devvp, &bn, &run);
if (error) if (error)
@ -269,37 +301,41 @@ genfs_do_putpages(struct vnode *vp, off_t startoff, off_t endoff, int flags,
if (bn == -1) if (bn == -1)
continue; continue;
/* only write max what we are allowed to write */ bp = getiobuf();
buf.b_bcount = xfersize;
if (smallest + bufoff + xfersize > eof)
buf.b_bcount -= (smallest+bufoff+xfersize) - eof;
buf.b_bcount = (buf.b_bcount + DEV_BSIZE-1) & ~(DEV_BSIZE-1);
KASSERT(buf.b_bcount > 0); /* only write max what we are allowed to write */
bp->b_bcount = xfersize;
if (smallest + bufoff + xfersize > eof)
bp->b_bcount -= (smallest+bufoff+xfersize) - eof;
bp->b_bcount = (bp->b_bcount + DEV_BSIZE-1) & ~(DEV_BSIZE-1);
KASSERT(bp->b_bcount > 0);
KASSERT(smallest >= 0); KASSERT(smallest >= 0);
DPRINTF(("putpages writing from %x to %x (vp size %x)\n", DPRINTF(("putpages writing from %x to %x (vp size %x)\n",
(int)(smallest + bufoff), (int)(smallest + bufoff),
(int)(smallest + bufoff + buf.b_bcount), (int)(smallest + bufoff + bp->b_bcount),
(int)eof)); (int)eof));
buf.b_bufsize = round_page(buf.b_bcount); bp->b_bufsize = round_page(bp->b_bcount);
buf.b_lblkno = 0; bp->b_lblkno = 0;
buf.b_blkno = bn + (((smallest+bufoff)&(bsize-1))>>DEV_BSHIFT); bp->b_blkno = bn + (((smallest+bufoff)&(bsize-1))>>DEV_BSHIFT);
buf.b_data = databuf + bufoff; bp->b_data = databuf + bufoff;
buf.b_vp = vp; bp->b_vp = vp;
buf.b_flags = B_WRITE | B_BUSY; bp->b_flags = B_WRITE | B_BUSY;
buf.b_iodone = uvm_aio_biodone; bp->b_iodone = uvm_aio_biodone;
if (async) { if (async) {
buf.b_flags |= B_CALL | B_ASYNC; bp->b_flags |= B_CALL | B_ASYNC;
buf.b_iodone = uvm_aio_biodone; bp->b_iodone = uvm_aio_biodone;
} }
vp->v_numoutput++; vp->v_numoutput++;
VOP_STRATEGY(devvp, &buf); VOP_STRATEGY(devvp, bp);
if (buf.b_error) if (bp->b_error)
panic("%s: VOP_STRATEGY lazy bum %d", panic("%s: VOP_STRATEGY lazy bum %d",
__func__, buf.b_error); __func__, bp->b_error);
if (!async)
putiobuf(bp);
} }
rumpvm_flushva(); rumpvm_flushva();