Make the buffer cache code MP-safe.
This commit is contained in:
parent
09843e3b7e
commit
338f31f581
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: fd.c,v 1.102 2003/01/30 16:33:50 hannken Exp $ */
|
||||
/* $NetBSD: fd.c,v 1.103 2003/02/05 21:38:38 pk Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
@ -2104,17 +2104,18 @@ fdformat(dev, finfo, p)
|
||||
struct ne7_fd_formb *finfo;
|
||||
struct proc *p;
|
||||
{
|
||||
int rv = 0, s;
|
||||
int rv = 0;
|
||||
struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
|
||||
struct fd_type *type = fd->sc_type;
|
||||
struct buf *bp;
|
||||
|
||||
/* set up a buffer header for fdstrategy() */
|
||||
bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT);
|
||||
if (bp == 0)
|
||||
bp = (struct buf *)pool_get(&bufpool, PR_NOWAIT);
|
||||
if (bp == NULL)
|
||||
return (ENOBUFS);
|
||||
|
||||
memset((void *)bp, 0, sizeof(struct buf));
|
||||
simple_lock_init(&bp->b_interlock);
|
||||
bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
|
||||
bp->b_proc = p;
|
||||
bp->b_dev = dev;
|
||||
@ -2159,23 +2160,8 @@ fdformat(dev, finfo, p)
|
||||
fdstrategy(bp);
|
||||
|
||||
/* ...and wait for it to complete */
|
||||
s = splbio();
|
||||
while (!(bp->b_flags & B_DONE)) {
|
||||
rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz);
|
||||
if (rv == EWOULDBLOCK)
|
||||
break;
|
||||
}
|
||||
splx(s);
|
||||
|
||||
if (rv == EWOULDBLOCK) {
|
||||
/* timed out */
|
||||
rv = EIO;
|
||||
biodone(bp);
|
||||
}
|
||||
if (bp->b_flags & B_ERROR) {
|
||||
rv = bp->b_error;
|
||||
}
|
||||
free(bp, M_TEMP);
|
||||
rv = biowait(bp);
|
||||
pool_put(&bufpool, bp);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ata_raid.c,v 1.1 2003/01/27 18:21:27 thorpej Exp $ */
|
||||
/* $NetBSD: ata_raid.c,v 1.2 2003/02/05 21:38:40 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Wasabi Systems, Inc.
|
||||
@ -296,6 +296,7 @@ ata_raid_config_block_rw(struct vnode *vp, daddr_t blkno, void *buf,
|
||||
int error;
|
||||
|
||||
bp = pool_get(&bufpool, PR_WAITOK);
|
||||
simple_lock_init(&bp->b_interlock);
|
||||
LIST_INIT(&bp->b_dep);
|
||||
|
||||
bp->b_vp = vp;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ccd.c,v 1.81 2003/01/25 23:09:58 kleink Exp $ */
|
||||
/* $NetBSD: ccd.c,v 1.82 2003/02/05 21:38:39 pk Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998, 1999 The NetBSD Foundation, Inc.
|
||||
@ -90,7 +90,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ccd.c,v 1.81 2003/01/25 23:09:58 kleink Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ccd.c,v 1.82 2003/02/05 21:38:39 pk Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -802,6 +802,7 @@ ccdbuffer(cs, bp, bn, addr, bcount)
|
||||
cbp = CCD_GETBUF();
|
||||
if (cbp == NULL)
|
||||
return (NULL);
|
||||
simple_lock_init(&cbp->cb_buf.b_interlock);
|
||||
cbp->cb_buf.b_flags = bp->b_flags | B_CALL;
|
||||
cbp->cb_buf.b_iodone = ccdiodone;
|
||||
cbp->cb_buf.b_proc = bp->b_proc;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cgd.c,v 1.6 2003/02/02 20:55:16 bouyer Exp $ */
|
||||
/* $NetBSD: cgd.c,v 1.7 2003/02/05 21:38:40 pk Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.6 2003/02/02 20:55:16 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.7 2003/02/05 21:38:40 pk Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
@ -307,6 +307,7 @@ cgdstart(struct dk_softc *dksc, struct buf *bp)
|
||||
disk_unbusy(&dksc->sc_dkdev, 0, (bp->b_flags & B_READ));
|
||||
return;
|
||||
}
|
||||
simple_lock_init(&cbp->cb_buf.b_interlock);
|
||||
cbp->cb_buf.b_data = newaddr;
|
||||
cbp->cb_buf.b_flags = bp->b_flags | B_CALL;
|
||||
cbp->cb_buf.b_iodone = cgdiodone;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: fd.c,v 1.36 2003/01/25 23:18:46 kleink Exp $ */
|
||||
/* $NetBSD: fd.c,v 1.37 2003/02/05 21:38:41 pk Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -92,7 +92,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: fd.c,v 1.36 2003/01/25 23:18:46 kleink Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: fd.c,v 1.37 2003/02/05 21:38:41 pk Exp $");
|
||||
|
||||
#include "rnd.h"
|
||||
#include "opt_ddb.h"
|
||||
@ -1486,9 +1486,12 @@ fdformat(dev, finfo, p)
|
||||
struct buf *bp;
|
||||
|
||||
/* set up a buffer header for fdstrategy() */
|
||||
bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT|M_ZERO);
|
||||
if(bp == 0)
|
||||
bp = (struct buf *)pool_get(&bufpool, PR_NOWAIT);
|
||||
if (bp == NULL)
|
||||
return ENOBUFS;
|
||||
|
||||
memset((void *)bp, 0, sizeof(struct buf));
|
||||
simple_lock_init(&bp->b_interlock);
|
||||
bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
|
||||
bp->b_proc = p;
|
||||
bp->b_dev = dev;
|
||||
@ -1512,23 +1515,8 @@ fdformat(dev, finfo, p)
|
||||
fdstrategy(bp);
|
||||
|
||||
/* ...and wait for it to complete */
|
||||
s = splbio();
|
||||
while (!(bp->b_flags & B_DONE)) {
|
||||
rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz);
|
||||
if (rv == EWOULDBLOCK)
|
||||
break;
|
||||
}
|
||||
splx(s);
|
||||
|
||||
if (rv == EWOULDBLOCK) {
|
||||
/* timed out */
|
||||
rv = EIO;
|
||||
biodone(bp);
|
||||
}
|
||||
if(bp->b_flags & B_ERROR) {
|
||||
rv = bp->b_error;
|
||||
}
|
||||
free(bp, M_TEMP);
|
||||
rv = biowait(bp);
|
||||
pool_put(&bufpool, bp);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: rf_netbsdkintf.c,v 1.153 2003/02/01 06:23:40 thorpej Exp $ */
|
||||
/* $NetBSD: rf_netbsdkintf.c,v 1.154 2003/02/05 21:38:40 pk Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
@ -111,7 +111,7 @@
|
||||
***********************************************************/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.153 2003/02/01 06:23:40 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.154 2003/02/05 21:38:40 pk Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/errno.h>
|
||||
@ -1835,6 +1835,12 @@ rf_DispatchKernelIO(queue, req)
|
||||
}
|
||||
#endif
|
||||
raidbp = pool_get(&raidframe_cbufpool, PR_NOWAIT);
|
||||
if (raidbp == NULL) {
|
||||
bp->b_flags |= B_ERROR;
|
||||
bp->b_error = ENOMEM;
|
||||
return (ENOMEM);
|
||||
}
|
||||
simple_lock_init(&raidbp->rf_buf.b_interlock);
|
||||
|
||||
/*
|
||||
* context for raidiodone
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cd.c,v 1.177 2003/02/03 23:50:59 thorpej Exp $ */
|
||||
/* $NetBSD: cd.c,v 1.178 2003/02/05 21:38:41 pk Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
|
||||
@ -54,7 +54,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.177 2003/02/03 23:50:59 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.178 2003/02/05 21:38:41 pk Exp $");
|
||||
|
||||
#include "rnd.h"
|
||||
|
||||
@ -647,6 +647,7 @@ cdstrategy(bp)
|
||||
}
|
||||
|
||||
/* Set up the IOP to the bounce buffer. */
|
||||
simple_lock_init(&nbp->b_interlock);
|
||||
nbp->b_error = 0;
|
||||
nbp->b_proc = bp->b_proc;
|
||||
nbp->b_vp = NULLVP;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vnd.c,v 1.90 2003/01/25 23:09:59 kleink Exp $ */
|
||||
/* $NetBSD: vnd.c,v 1.91 2003/02/05 21:38:39 pk Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
|
||||
@ -98,7 +98,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.90 2003/01/25 23:09:59 kleink Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.91 2003/02/05 21:38:39 pk Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "fs_nfs.h"
|
||||
@ -490,6 +490,7 @@ vndstrategy(bp)
|
||||
s = splbio();
|
||||
nbp = VND_GETBUF(vnd);
|
||||
splx(s);
|
||||
simple_lock_init(&nbp->vb_buf.b_interlock);
|
||||
nbp->vb_buf.b_flags = flags;
|
||||
nbp->vb_buf.b_bcount = sz;
|
||||
nbp->vb_buf.b_bufsize = round_page((ulong)addr + sz)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: kern_physio.c,v 1.54 2003/01/18 10:06:28 thorpej Exp $ */
|
||||
/* $NetBSD: kern_physio.c,v 1.55 2003/02/05 21:38:42 pk Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1994 Christopher G. Demetriou
|
||||
@ -42,7 +42,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_physio.c,v 1.54 2003/01/18 10:06:28 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_physio.c,v 1.55 2003/02/05 21:38:42 pk Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -275,6 +275,7 @@ getphysbuf()
|
||||
bp = pool_get(&bufpool, PR_WAITOK);
|
||||
splx(s);
|
||||
memset(bp, 0, sizeof(*bp));
|
||||
simple_lock_init(&bp->b_interlock);
|
||||
return(bp);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_bio.c,v 1.86 2003/01/18 10:06:37 thorpej Exp $ */
|
||||
/* $NetBSD: vfs_bio.c,v 1.87 2003/02/05 21:38:42 pk Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1994 Christopher G. Demetriou
|
||||
@ -51,7 +51,7 @@
|
||||
#include "opt_softdep.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_bio.c,v 1.86 2003/01/18 10:06:37 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_bio.c,v 1.87 2003/02/05 21:38:42 pk Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -102,27 +102,35 @@ struct bio_ops bioops; /* I/O operation notification */
|
||||
TAILQ_HEAD(bqueues, buf) bufqueues[BQUEUES];
|
||||
int needbuffer;
|
||||
|
||||
/*
|
||||
* Buffer queue lock.
|
||||
* Take this lock first if also taking some buffer's b_interlock.
|
||||
*/
|
||||
struct simplelock bqueue_slock = SIMPLELOCK_INITIALIZER;
|
||||
|
||||
/*
|
||||
* Buffer pool for I/O buffers.
|
||||
*/
|
||||
struct pool bufpool;
|
||||
|
||||
/*
|
||||
* bread()/breadn() helper.
|
||||
*/
|
||||
static __inline struct buf *bio_doread(struct vnode *, daddr_t, int,
|
||||
struct ucred *, int);
|
||||
int count_lock_queue(void);
|
||||
|
||||
/*
|
||||
* Insq/Remq for the buffer free lists.
|
||||
* Call with buffer queue locked.
|
||||
*/
|
||||
#define binsheadfree(bp, dp) TAILQ_INSERT_HEAD(dp, bp, b_freelist)
|
||||
#define binstailfree(bp, dp) TAILQ_INSERT_TAIL(dp, bp, b_freelist)
|
||||
|
||||
static __inline struct buf *bio_doread __P((struct vnode *, daddr_t, int,
|
||||
struct ucred *, int));
|
||||
int count_lock_queue __P((void));
|
||||
|
||||
void
|
||||
bremfree(bp)
|
||||
struct buf *bp;
|
||||
{
|
||||
int s = splbio();
|
||||
|
||||
struct bqueues *dp = NULL;
|
||||
|
||||
/*
|
||||
@ -140,7 +148,6 @@ bremfree(bp)
|
||||
panic("bremfree: lost tail");
|
||||
}
|
||||
TAILQ_REMOVE(dp, bp, b_freelist);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -168,6 +175,7 @@ bufinit()
|
||||
for (i = 0; i < nbuf; i++) {
|
||||
bp = &buf[i];
|
||||
memset((char *)bp, 0, sizeof(*bp));
|
||||
simple_lock_init(&bp->b_interlock);
|
||||
bp->b_dev = NODEV;
|
||||
bp->b_vnbufs.le_next = NOLIST;
|
||||
LIST_INIT(&bp->b_dep);
|
||||
@ -206,7 +214,7 @@ bio_doread(vp, blkno, size, cred, async)
|
||||
/*
|
||||
* If buffer does not have data valid, start a read.
|
||||
* Note that if buffer is B_INVAL, getblk() won't return it.
|
||||
* Therefore, it's valid if it's I/O has completed or been delayed.
|
||||
* Therefore, it's valid if its I/O has completed or been delayed.
|
||||
*/
|
||||
if (!ISSET(bp->b_flags, (B_DONE | B_DELWRI))) {
|
||||
/* Start I/O for the buffer. */
|
||||
@ -307,6 +315,8 @@ bwrite(bp)
|
||||
struct vnode *vp;
|
||||
struct mount *mp;
|
||||
|
||||
KASSERT(ISSET(bp->b_flags, B_BUSY));
|
||||
|
||||
vp = bp->b_vp;
|
||||
if (vp != NULL) {
|
||||
if (vp->v_type == VBLK)
|
||||
@ -345,6 +355,7 @@ bwrite(bp)
|
||||
wasdelayed = ISSET(bp->b_flags, B_DELWRI);
|
||||
|
||||
s = splbio();
|
||||
simple_lock(&bp->b_interlock);
|
||||
|
||||
CLR(bp->b_flags, (B_READ | B_DONE | B_ERROR | B_DELWRI));
|
||||
|
||||
@ -358,7 +369,8 @@ bwrite(bp)
|
||||
p->p_stats->p_ru.ru_oublock++;
|
||||
|
||||
/* Initiate disk write. Make sure the appropriate party is charged. */
|
||||
bp->b_vp->v_numoutput++;
|
||||
V_INCR_NUMOUTPUT(bp->b_vp);
|
||||
simple_unlock(&bp->b_interlock);
|
||||
splx(s);
|
||||
|
||||
VOP_STRATEGY(bp);
|
||||
@ -407,6 +419,8 @@ bdwrite(bp)
|
||||
const struct bdevsw *bdev;
|
||||
int s;
|
||||
|
||||
KASSERT(ISSET(bp->b_flags, B_BUSY));
|
||||
|
||||
/* If this is a tape block, write the block now. */
|
||||
/* XXX NOTE: the memory filesystem usurpes major device */
|
||||
/* XXX number 4095, which is a bad idea. */
|
||||
@ -425,6 +439,7 @@ bdwrite(bp)
|
||||
* (3) Make sure it's on its vnode's correct block list.
|
||||
*/
|
||||
s = splbio();
|
||||
simple_lock(&bp->b_interlock);
|
||||
|
||||
if (!ISSET(bp->b_flags, B_DELWRI)) {
|
||||
SET(bp->b_flags, B_DELWRI);
|
||||
@ -434,6 +449,7 @@ bdwrite(bp)
|
||||
|
||||
/* Otherwise, the "write" is done, so mark and release the buffer. */
|
||||
CLR(bp->b_flags, B_NEEDCOMMIT|B_DONE);
|
||||
simple_unlock(&bp->b_interlock);
|
||||
splx(s);
|
||||
|
||||
brelse(bp);
|
||||
@ -446,8 +462,15 @@ void
|
||||
bawrite(bp)
|
||||
struct buf *bp;
|
||||
{
|
||||
int s;
|
||||
|
||||
KASSERT(ISSET(bp->b_flags, B_BUSY));
|
||||
|
||||
s = splbio();
|
||||
simple_lock(&bp->b_interlock);
|
||||
SET(bp->b_flags, B_ASYNC);
|
||||
simple_unlock(&bp->b_interlock);
|
||||
splx(s);
|
||||
VOP_BWRITE(bp);
|
||||
}
|
||||
|
||||
@ -462,7 +485,10 @@ bdirty(bp)
|
||||
struct proc *p = l->l_proc;
|
||||
int s;
|
||||
|
||||
KASSERT(ISSET(bp->b_flags, B_BUSY));
|
||||
|
||||
s = splbio();
|
||||
simple_lock(&bp->b_interlock);
|
||||
|
||||
CLR(bp->b_flags, B_AGE);
|
||||
|
||||
@ -472,6 +498,7 @@ bdirty(bp)
|
||||
reassignbuf(bp, bp->b_vp);
|
||||
}
|
||||
|
||||
simple_unlock(&bp->b_interlock);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
@ -488,15 +515,17 @@ brelse(bp)
|
||||
|
||||
KASSERT(ISSET(bp->b_flags, B_BUSY));
|
||||
|
||||
/* Block disk interrupts. */
|
||||
s = splbio();
|
||||
simple_lock(&bqueue_slock);
|
||||
simple_lock(&bp->b_interlock);
|
||||
|
||||
/* Wake up any processes waiting for any buffer to become free. */
|
||||
if (needbuffer) {
|
||||
needbuffer = 0;
|
||||
wakeup(&needbuffer);
|
||||
}
|
||||
|
||||
/* Block disk interrupts. */
|
||||
s = splbio();
|
||||
|
||||
/* Wake up any proceeses waiting for _this_ buffer to become free. */
|
||||
if (ISSET(bp->b_flags, B_WANTED)) {
|
||||
CLR(bp->b_flags, B_WANTED|B_AGE);
|
||||
@ -584,6 +613,8 @@ already_queued:
|
||||
SET(bp->b_flags, B_CACHE);
|
||||
|
||||
/* Allow disk interrupts. */
|
||||
simple_unlock(&bp->b_interlock);
|
||||
simple_unlock(&bqueue_slock);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
@ -629,17 +660,21 @@ getblk(vp, blkno, size, slpflag, slptimeo)
|
||||
int s, err;
|
||||
|
||||
start:
|
||||
s = splbio();
|
||||
simple_lock(&bqueue_slock);
|
||||
bp = incore(vp, blkno);
|
||||
if (bp != NULL) {
|
||||
s = splbio();
|
||||
simple_lock(&bp->b_interlock);
|
||||
if (ISSET(bp->b_flags, B_BUSY)) {
|
||||
simple_unlock(&bqueue_slock);
|
||||
if (curproc == uvm.pagedaemon_proc) {
|
||||
simple_unlock(&bp->b_interlock);
|
||||
splx(s);
|
||||
return NULL;
|
||||
}
|
||||
SET(bp->b_flags, B_WANTED);
|
||||
err = tsleep(bp, slpflag | (PRIBIO + 1), "getblk",
|
||||
slptimeo);
|
||||
err = ltsleep(bp, slpflag | (PRIBIO + 1) | PNORELOCK,
|
||||
"getblk", slptimeo, &bp->b_interlock);
|
||||
splx(s);
|
||||
if (err)
|
||||
return (NULL);
|
||||
@ -652,17 +687,20 @@ start:
|
||||
#endif
|
||||
SET(bp->b_flags, B_BUSY);
|
||||
bremfree(bp);
|
||||
splx(s);
|
||||
} else {
|
||||
if ((bp = getnewbuf(slpflag, slptimeo)) == NULL)
|
||||
if ((bp = getnewbuf(slpflag, slptimeo)) == NULL) {
|
||||
simple_unlock(&bqueue_slock);
|
||||
splx(s);
|
||||
goto start;
|
||||
}
|
||||
|
||||
binshash(bp, BUFHASH(vp, blkno));
|
||||
bp->b_blkno = bp->b_lblkno = bp->b_rawblkno = blkno;
|
||||
s = splbio();
|
||||
bgetvp(vp, bp);
|
||||
splx(s);
|
||||
}
|
||||
simple_unlock(&bp->b_interlock);
|
||||
simple_unlock(&bqueue_slock);
|
||||
splx(s);
|
||||
allocbuf(bp, size);
|
||||
return (bp);
|
||||
}
|
||||
@ -675,11 +713,18 @@ geteblk(size)
|
||||
int size;
|
||||
{
|
||||
struct buf *bp;
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
simple_lock(&bqueue_slock);
|
||||
while ((bp = getnewbuf(0, 0)) == 0)
|
||||
;
|
||||
|
||||
SET(bp->b_flags, B_INVAL);
|
||||
binshash(bp, &invalhash);
|
||||
simple_unlock(&bqueue_slock);
|
||||
simple_unlock(&bp->b_interlock);
|
||||
splx(s);
|
||||
allocbuf(bp, size);
|
||||
return (bp);
|
||||
}
|
||||
@ -717,12 +762,18 @@ allocbuf(bp, size)
|
||||
int amt;
|
||||
|
||||
/* find a buffer */
|
||||
s = splbio();
|
||||
simple_lock(&bqueue_slock);
|
||||
while ((nbp = getnewbuf(0, 0)) == NULL)
|
||||
;
|
||||
|
||||
SET(nbp->b_flags, B_INVAL);
|
||||
binshash(nbp, &invalhash);
|
||||
|
||||
simple_unlock(&nbp->b_interlock);
|
||||
simple_unlock(&bqueue_slock);
|
||||
splx(s);
|
||||
|
||||
/* and steal its pages, up to the amount we need */
|
||||
amt = min(nbp->b_bufsize, (desired_size - bp->b_bufsize));
|
||||
pagemove((nbp->b_data + nbp->b_bufsize - amt),
|
||||
@ -738,7 +789,6 @@ allocbuf(bp, size)
|
||||
if (nbp->b_bufsize < 0)
|
||||
panic("allocbuf: negative bufsize");
|
||||
#endif
|
||||
|
||||
brelse(nbp);
|
||||
}
|
||||
|
||||
@ -750,13 +800,17 @@ allocbuf(bp, size)
|
||||
*/
|
||||
if (bp->b_bufsize > desired_size) {
|
||||
s = splbio();
|
||||
simple_lock(&bqueue_slock);
|
||||
if ((nbp = TAILQ_FIRST(&bufqueues[BQ_EMPTY])) == NULL) {
|
||||
/* No free buffer head */
|
||||
simple_unlock(&bqueue_slock);
|
||||
splx(s);
|
||||
goto out;
|
||||
}
|
||||
/* No need to lock nbp since it came from the empty queue */
|
||||
bremfree(nbp);
|
||||
SET(nbp->b_flags, B_BUSY);
|
||||
SET(nbp->b_flags, B_BUSY | B_INVAL);
|
||||
simple_unlock(&bqueue_slock);
|
||||
splx(s);
|
||||
|
||||
/* move the page to it and note this change */
|
||||
@ -765,7 +819,6 @@ allocbuf(bp, size)
|
||||
nbp->b_bufsize = bp->b_bufsize - desired_size;
|
||||
bp->b_bufsize = desired_size;
|
||||
nbp->b_bcount = 0;
|
||||
SET(nbp->b_flags, B_INVAL);
|
||||
|
||||
/* release the newly-filled buffer and leave */
|
||||
brelse(nbp);
|
||||
@ -779,24 +832,28 @@ out:
|
||||
* Find a buffer which is available for use.
|
||||
* Select something from a free list.
|
||||
* Preference is to AGE list, then LRU list.
|
||||
*
|
||||
* Called with buffer queues locked.
|
||||
* Return buffer locked.
|
||||
*/
|
||||
struct buf *
|
||||
getnewbuf(slpflag, slptimeo)
|
||||
int slpflag, slptimeo;
|
||||
{
|
||||
struct buf *bp;
|
||||
int s;
|
||||
|
||||
start:
|
||||
s = splbio();
|
||||
LOCK_ASSERT(simple_lock_held(&bqueue_slock));
|
||||
|
||||
if ((bp = TAILQ_FIRST(&bufqueues[BQ_AGE])) != NULL ||
|
||||
(bp = TAILQ_FIRST(&bufqueues[BQ_LRU])) != NULL) {
|
||||
simple_lock(&bp->b_interlock);
|
||||
bremfree(bp);
|
||||
} else {
|
||||
/* wait for a free buffer of any kind */
|
||||
needbuffer = 1;
|
||||
tsleep(&needbuffer, slpflag|(PRIBIO+1), "getnewbuf", slptimeo);
|
||||
splx(s);
|
||||
ltsleep(&needbuffer, slpflag|(PRIBIO+1),
|
||||
"getnewbuf", slptimeo, &bqueue_slock);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -808,7 +865,7 @@ start:
|
||||
*/
|
||||
CLR(bp->b_flags, B_VFLUSH);
|
||||
SET(bp->b_flags, B_AGE);
|
||||
splx(s);
|
||||
simple_unlock(&bp->b_interlock);
|
||||
goto start;
|
||||
}
|
||||
|
||||
@ -820,12 +877,12 @@ start:
|
||||
* (since we might sleep while starting the write).
|
||||
*/
|
||||
if (ISSET(bp->b_flags, B_DELWRI)) {
|
||||
splx(s);
|
||||
/*
|
||||
* This buffer has gone through the LRU, so make sure it gets
|
||||
* reused ASAP.
|
||||
*/
|
||||
SET(bp->b_flags, B_AGE);
|
||||
simple_unlock(&bp->b_interlock);
|
||||
bawrite(bp);
|
||||
return (NULL);
|
||||
}
|
||||
@ -833,7 +890,6 @@ start:
|
||||
/* disassociate us from our vnode, if we had one... */
|
||||
if (bp->b_vp)
|
||||
brelvp(bp);
|
||||
splx(s);
|
||||
|
||||
if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_deallocate)
|
||||
(*bioops.io_deallocate)(bp);
|
||||
@ -859,21 +915,25 @@ int
|
||||
biowait(bp)
|
||||
struct buf *bp;
|
||||
{
|
||||
int s;
|
||||
int s, error;
|
||||
|
||||
s = splbio();
|
||||
simple_lock(&bp->b_interlock);
|
||||
while (!ISSET(bp->b_flags, B_DONE | B_DELWRI))
|
||||
tsleep(bp, PRIBIO + 1, "biowait", 0);
|
||||
splx(s);
|
||||
ltsleep(bp, PRIBIO + 1, "biowait", 0, &bp->b_interlock);
|
||||
|
||||
/* check for interruption of I/O (e.g. via NFS), then errors. */
|
||||
if (ISSET(bp->b_flags, B_EINTR)) {
|
||||
CLR(bp->b_flags, B_EINTR);
|
||||
return (EINTR);
|
||||
error = EINTR;
|
||||
} else if (ISSET(bp->b_flags, B_ERROR))
|
||||
return (bp->b_error ? bp->b_error : EIO);
|
||||
error = bp->b_error ? bp->b_error : EIO;
|
||||
else
|
||||
return (0);
|
||||
error = 0;
|
||||
|
||||
simple_unlock(&bp->b_interlock);
|
||||
splx(s);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -898,6 +958,7 @@ biodone(bp)
|
||||
{
|
||||
int s = splbio();
|
||||
|
||||
simple_lock(&bp->b_interlock);
|
||||
if (ISSET(bp->b_flags, B_DONE))
|
||||
panic("biodone already");
|
||||
SET(bp->b_flags, B_DONE); /* note that it's done */
|
||||
@ -908,15 +969,22 @@ biodone(bp)
|
||||
if (!ISSET(bp->b_flags, B_READ)) /* wake up reader */
|
||||
vwakeup(bp);
|
||||
|
||||
if (ISSET(bp->b_flags, B_CALL)) { /* if necessary, call out */
|
||||
/*
|
||||
* If necessary, call out. Unlock the buffer before calling
|
||||
* iodone() as the buffer isn't valid any more when it return.
|
||||
*/
|
||||
if (ISSET(bp->b_flags, B_CALL)) {
|
||||
CLR(bp->b_flags, B_CALL); /* but note callout done */
|
||||
simple_unlock(&bp->b_interlock);
|
||||
(*bp->b_iodone)(bp);
|
||||
} else {
|
||||
if (ISSET(bp->b_flags, B_ASYNC)) /* if async, release */
|
||||
if (ISSET(bp->b_flags, B_ASYNC)) { /* if async, release */
|
||||
simple_unlock(&bp->b_interlock);
|
||||
brelse(bp);
|
||||
else { /* or just wakeup the buffer */
|
||||
} else { /* or just wakeup the buffer */
|
||||
CLR(bp->b_flags, B_WANTED);
|
||||
wakeup(bp);
|
||||
simple_unlock(&bp->b_interlock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -932,8 +1000,10 @@ count_lock_queue()
|
||||
struct buf *bp;
|
||||
int n = 0;
|
||||
|
||||
simple_lock(&bqueue_slock);
|
||||
TAILQ_FOREACH(bp, &bufqueues[BQ_LOCKED], b_freelist)
|
||||
n++;
|
||||
simple_unlock(&bqueue_slock);
|
||||
return (n);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_subr.c,v 1.186 2003/02/01 06:23:45 thorpej Exp $ */
|
||||
/* $NetBSD: vfs_subr.c,v 1.187 2003/02/05 21:38:42 pk Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
|
||||
@ -82,7 +82,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.186 2003/02/01 06:23:45 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.187 2003/02/05 21:38:42 pk Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_compat_netbsd.h"
|
||||
@ -158,6 +158,9 @@ struct simplelock mntvnode_slock = SIMPLELOCK_INITIALIZER;
|
||||
struct simplelock vnode_free_list_slock = SIMPLELOCK_INITIALIZER;
|
||||
struct simplelock spechash_slock = SIMPLELOCK_INITIALIZER;
|
||||
|
||||
/* XXX - gross; single global lock to protect v_numoutput */
|
||||
struct simplelock global_v_numoutput_slock = SIMPLELOCK_INITIALIZER;
|
||||
|
||||
/*
|
||||
* These define the root filesystem and device.
|
||||
*/
|
||||
@ -640,12 +643,18 @@ vwakeup(bp)
|
||||
struct vnode *vp;
|
||||
|
||||
if ((vp = bp->b_vp) != NULL) {
|
||||
/* XXX global lock hack
|
||||
* can't use v_interlock here since this is called
|
||||
* in interrupt context from biodone().
|
||||
*/
|
||||
simple_lock(&global_v_numoutput_slock);
|
||||
if (--vp->v_numoutput < 0)
|
||||
panic("vwakeup: neg numoutput, vp %p", vp);
|
||||
if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
|
||||
vp->v_flag &= ~VBWAIT;
|
||||
wakeup((caddr_t)&vp->v_numoutput);
|
||||
}
|
||||
simple_unlock(&global_v_numoutput_slock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -691,10 +700,12 @@ vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
|
||||
restart:
|
||||
for (bp = LIST_FIRST(&vp->v_cleanblkhd); bp; bp = nbp) {
|
||||
nbp = LIST_NEXT(bp, b_vnbufs);
|
||||
simple_lock(&bp->b_interlock);
|
||||
if (bp->b_flags & B_BUSY) {
|
||||
bp->b_flags |= B_WANTED;
|
||||
error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),
|
||||
"vinvalbuf", slptimeo);
|
||||
error = ltsleep((caddr_t)bp,
|
||||
slpflag | (PRIBIO + 1) | PNORELOCK,
|
||||
"vinvalbuf", slptimeo, &bp->b_interlock);
|
||||
if (error) {
|
||||
splx(s);
|
||||
return (error);
|
||||
@ -702,15 +713,18 @@ restart:
|
||||
goto restart;
|
||||
}
|
||||
bp->b_flags |= B_BUSY | B_INVAL | B_VFLUSH;
|
||||
simple_unlock(&bp->b_interlock);
|
||||
brelse(bp);
|
||||
}
|
||||
|
||||
for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
|
||||
nbp = LIST_NEXT(bp, b_vnbufs);
|
||||
simple_lock(&bp->b_interlock);
|
||||
if (bp->b_flags & B_BUSY) {
|
||||
bp->b_flags |= B_WANTED;
|
||||
error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),
|
||||
"vinvalbuf", slptimeo);
|
||||
error = ltsleep((caddr_t)bp,
|
||||
slpflag | (PRIBIO + 1) | PNORELOCK,
|
||||
"vinvalbuf", slptimeo, &bp->b_interlock);
|
||||
if (error) {
|
||||
splx(s);
|
||||
return (error);
|
||||
@ -727,10 +741,12 @@ restart:
|
||||
printf("buffer still DELWRI\n");
|
||||
#endif
|
||||
bp->b_flags |= B_BUSY | B_VFLUSH;
|
||||
simple_unlock(&bp->b_interlock);
|
||||
VOP_BWRITE(bp);
|
||||
goto restart;
|
||||
}
|
||||
bp->b_flags |= B_BUSY | B_INVAL | B_VFLUSH;
|
||||
simple_unlock(&bp->b_interlock);
|
||||
brelse(bp);
|
||||
}
|
||||
|
||||
@ -773,10 +789,11 @@ restart:
|
||||
nbp = LIST_NEXT(bp, b_vnbufs);
|
||||
if (bp->b_lblkno < lbn)
|
||||
continue;
|
||||
simple_lock(&bp->b_interlock);
|
||||
if (bp->b_flags & B_BUSY) {
|
||||
bp->b_flags |= B_WANTED;
|
||||
error = tsleep(bp, slpflag | (PRIBIO + 1),
|
||||
"vtruncbuf", slptimeo);
|
||||
error = ltsleep(bp, slpflag | (PRIBIO + 1) | PNORELOCK,
|
||||
"vtruncbuf", slptimeo, &bp->b_interlock);
|
||||
if (error) {
|
||||
splx(s);
|
||||
return (error);
|
||||
@ -784,6 +801,7 @@ restart:
|
||||
goto restart;
|
||||
}
|
||||
bp->b_flags |= B_BUSY | B_INVAL | B_VFLUSH;
|
||||
simple_unlock(&bp->b_interlock);
|
||||
brelse(bp);
|
||||
}
|
||||
|
||||
@ -791,10 +809,11 @@ restart:
|
||||
nbp = LIST_NEXT(bp, b_vnbufs);
|
||||
if (bp->b_lblkno < lbn)
|
||||
continue;
|
||||
simple_lock(&bp->b_interlock);
|
||||
if (bp->b_flags & B_BUSY) {
|
||||
bp->b_flags |= B_WANTED;
|
||||
error = tsleep(bp, slpflag | (PRIBIO + 1),
|
||||
"vtruncbuf", slptimeo);
|
||||
error = ltsleep(bp, slpflag | (PRIBIO + 1) | PNORELOCK,
|
||||
"vtruncbuf", slptimeo, &bp->b_interlock);
|
||||
if (error) {
|
||||
splx(s);
|
||||
return (error);
|
||||
@ -802,6 +821,7 @@ restart:
|
||||
goto restart;
|
||||
}
|
||||
bp->b_flags |= B_BUSY | B_INVAL | B_VFLUSH;
|
||||
simple_unlock(&bp->b_interlock);
|
||||
brelse(bp);
|
||||
}
|
||||
|
||||
@ -826,11 +846,15 @@ loop:
|
||||
s = splbio();
|
||||
for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
|
||||
nbp = LIST_NEXT(bp, b_vnbufs);
|
||||
if ((bp->b_flags & B_BUSY))
|
||||
simple_lock(&bp->b_interlock);
|
||||
if ((bp->b_flags & B_BUSY)) {
|
||||
simple_unlock(&bp->b_interlock);
|
||||
continue;
|
||||
}
|
||||
if ((bp->b_flags & B_DELWRI) == 0)
|
||||
panic("vflushbuf: not dirty, bp %p", bp);
|
||||
bp->b_flags |= B_BUSY | B_VFLUSH;
|
||||
simple_unlock(&bp->b_interlock);
|
||||
splx(s);
|
||||
/*
|
||||
* Wait for I/O associated with indirect blocks to complete,
|
||||
@ -846,10 +870,13 @@ loop:
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
simple_lock(&global_v_numoutput_slock);
|
||||
while (vp->v_numoutput) {
|
||||
vp->v_flag |= VBWAIT;
|
||||
tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "vflushbuf", 0);
|
||||
ltsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "vflushbuf", 0,
|
||||
&global_v_numoutput_slock);
|
||||
}
|
||||
simple_unlock(&global_v_numoutput_slock);
|
||||
splx(s);
|
||||
if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
|
||||
vprint("vflushbuf: dirty", vp);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: genfs_vnops.c,v 1.70 2003/01/21 00:01:14 christos Exp $ */
|
||||
/* $NetBSD: genfs_vnops.c,v 1.71 2003/02/05 21:38:42 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
@ -35,7 +35,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.70 2003/01/21 00:01:14 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.71 2003/02/05 21:38:42 pk Exp $");
|
||||
|
||||
#include "opt_nfsserver.h"
|
||||
|
||||
@ -653,6 +653,7 @@ genfs_getpages(void *v)
|
||||
s = splbio();
|
||||
mbp = pool_get(&bufpool, PR_WAITOK);
|
||||
splx(s);
|
||||
simple_lock_init(&mbp->b_interlock);
|
||||
mbp->b_bufsize = totalbytes;
|
||||
mbp->b_data = (void *)kva;
|
||||
mbp->b_resid = mbp->b_bcount = bytes;
|
||||
@ -786,6 +787,7 @@ genfs_getpages(void *v)
|
||||
s = splbio();
|
||||
bp = pool_get(&bufpool, PR_WAITOK);
|
||||
splx(s);
|
||||
simple_lock_init(&bp->b_interlock);
|
||||
bp->b_data = (char *)kva + offset - startoffset;
|
||||
bp->b_resid = bp->b_bcount = iobytes;
|
||||
bp->b_flags = B_BUSY|B_READ|B_CALL|B_ASYNC;
|
||||
@ -1067,7 +1069,9 @@ genfs_putpages(void *v)
|
||||
|
||||
error = 0;
|
||||
s = splbio();
|
||||
simple_lock(&global_v_numoutput_slock);
|
||||
wasclean = (vp->v_numoutput == 0);
|
||||
simple_unlock(&global_v_numoutput_slock);
|
||||
splx(s);
|
||||
off = startoff;
|
||||
if (endoff == 0 || flags & PGO_ALLPAGES) {
|
||||
@ -1341,10 +1345,16 @@ genfs_putpages(void *v)
|
||||
splx(s);
|
||||
if (!wasclean && !async) {
|
||||
s = splbio();
|
||||
/*
|
||||
* XXX - we want simple_unlock(&global_v_numoutput_slock);
|
||||
* but the slot in ltsleep() is taken!
|
||||
* XXX - try to recover from missed wakeups with a timeout..
|
||||
* must think of something better.
|
||||
*/
|
||||
while (vp->v_numoutput != 0) {
|
||||
vp->v_flag |= VBWAIT;
|
||||
UVM_UNLOCK_AND_WAIT(&vp->v_numoutput, slock, FALSE,
|
||||
"genput2", 0);
|
||||
"genput2", hz);
|
||||
simple_lock(slock);
|
||||
}
|
||||
splx(s);
|
||||
@ -1390,8 +1400,11 @@ genfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags)
|
||||
UVMPAGER_MAPIN_WRITE | UVMPAGER_MAPIN_WAITOK);
|
||||
|
||||
s = splbio();
|
||||
simple_lock(&global_v_numoutput_slock);
|
||||
vp->v_numoutput += 2;
|
||||
simple_unlock(&global_v_numoutput_slock);
|
||||
mbp = pool_get(&bufpool, PR_WAITOK);
|
||||
simple_lock_init(&mbp->b_interlock);
|
||||
UVMHIST_LOG(ubchist, "vp %p mbp %p num now %d bytes 0x%x",
|
||||
vp, mbp, vp->v_numoutput, bytes);
|
||||
splx(s);
|
||||
@ -1428,11 +1441,12 @@ genfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags)
|
||||
bp = mbp;
|
||||
} else {
|
||||
s = splbio();
|
||||
vp->v_numoutput++;
|
||||
V_INCR_NUMOUTPUT(vp);
|
||||
bp = pool_get(&bufpool, PR_WAITOK);
|
||||
UVMHIST_LOG(ubchist, "vp %p bp %p num now %d",
|
||||
vp, bp, vp->v_numoutput, 0);
|
||||
splx(s);
|
||||
simple_lock_init(&bp->b_interlock);
|
||||
bp->b_data = (char *)kva +
|
||||
(vaddr_t)(offset - pg->offset);
|
||||
bp->b_resid = bp->b_bcount = iobytes;
|
||||
@ -1635,10 +1649,11 @@ genfs_compat_gop_write(struct vnode *vp, struct vm_page **pgs, int npages,
|
||||
error = VOP_WRITE(vp, &uio, 0, cred);
|
||||
|
||||
s = splbio();
|
||||
vp->v_numoutput++;
|
||||
V_INCR_NUMOUTPUT(vp);
|
||||
bp = pool_get(&bufpool, PR_WAITOK);
|
||||
splx(s);
|
||||
|
||||
simple_lock_init(&bp->b_interlock);
|
||||
bp->b_flags = B_BUSY | B_WRITE | B_AGE;
|
||||
bp->b_vp = vp;
|
||||
bp->b_lblkno = offset >> vp->v_mount->mnt_fs_bshift;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: buf.h,v 1.56 2003/02/01 21:07:02 erh Exp $ */
|
||||
/* $NetBSD: buf.h,v 1.57 2003/02/05 21:38:43 pk Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -82,6 +82,7 @@
|
||||
|
||||
#include <sys/pool.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/lock.h>
|
||||
|
||||
struct buf;
|
||||
struct mount;
|
||||
@ -158,6 +159,7 @@ struct buf {
|
||||
TAILQ_ENTRY(buf) b_actq; /* Device driver queue when active. */
|
||||
struct proc *b_proc; /* Associated proc if B_PHYS set. */
|
||||
volatile long b_flags; /* B_* flags. */
|
||||
struct simplelock b_interlock; /* Lock for b_flags changes */
|
||||
int b_error; /* Errno value. */
|
||||
long b_bufsize; /* Allocated buffer size. */
|
||||
long b_bcount; /* Valid bytes in buffer. */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vnode.h,v 1.102 2003/02/01 06:23:52 thorpej Exp $ */
|
||||
/* $NetBSD: vnode.h,v 1.103 2003/02/05 21:38:43 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
@ -156,6 +156,18 @@ struct vnode {
|
||||
|
||||
#define VSIZENOTSET ((voff_t)-1)
|
||||
|
||||
/*
|
||||
* Use a global lock for all v_numoutput updates.
|
||||
* Define a convenience macro to increment by one.
|
||||
* Note: the only place where v_numoutput is decremented is in vwakeup().
|
||||
*/
|
||||
extern struct simplelock global_v_numoutput_slock;
|
||||
#define V_INCR_NUMOUTPUT(vp) do { \
|
||||
simple_lock(&global_v_numoutput_slock); \
|
||||
(vp)->v_numoutput++; \
|
||||
simple_unlock(&global_v_numoutput_slock); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/*
|
||||
* Valid states for the fingerprint flag - if signed exec is being used
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ffs_softdep.c,v 1.43 2003/02/01 06:23:52 thorpej Exp $ */
|
||||
/* $NetBSD: ffs_softdep.c,v 1.44 2003/02/05 21:38:43 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 1998 Marshall Kirk McKusick. All Rights Reserved.
|
||||
@ -33,7 +33,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ffs_softdep.c,v 1.43 2003/02/01 06:23:52 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ffs_softdep.c,v 1.44 2003/02/05 21:38:43 pk Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/buf.h>
|
||||
@ -5226,14 +5226,17 @@ drain_output(vp, islocked)
|
||||
|
||||
if (!islocked)
|
||||
ACQUIRE_LOCK(&lk);
|
||||
simple_lock(&global_v_numoutput_slock);
|
||||
while (vp->v_numoutput) {
|
||||
int s;
|
||||
|
||||
vp->v_flag |= VBWAIT;
|
||||
s = FREE_LOCK_INTERLOCKED(&lk);
|
||||
tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "drainvp", 0);
|
||||
ltsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "drainvp", 0,
|
||||
&global_v_numoutput_slock);
|
||||
ACQUIRE_LOCK_INTERLOCKED(&lk, s);
|
||||
}
|
||||
simple_unlock(&global_v_numoutput_slock);
|
||||
if (!islocked)
|
||||
FREE_LOCK(&lk);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ffs_vnops.c,v 1.53 2003/01/29 03:06:40 simonb Exp $ */
|
||||
/* $NetBSD: ffs_vnops.c,v 1.54 2003/02/05 21:38:44 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
@ -36,7 +36,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.53 2003/01/29 03:06:40 simonb Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.54 2003/02/05 21:38:44 pk Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -306,10 +306,13 @@ ffs_fsync(v)
|
||||
}
|
||||
|
||||
if (ap->a_flags & FSYNC_WAIT) {
|
||||
simple_lock(&global_v_numoutput_slock);
|
||||
while (vp->v_numoutput > 0) {
|
||||
vp->v_flag |= VBWAIT;
|
||||
tsleep(&vp->v_numoutput, PRIBIO + 1, "fsync_range", 0);
|
||||
ltsleep(&vp->v_numoutput, PRIBIO + 1, "fsync_range", 0,
|
||||
&global_v_numoutput_slock);
|
||||
}
|
||||
simple_unlock(&global_v_numoutput_slock);
|
||||
}
|
||||
splx(s);
|
||||
|
||||
@ -398,11 +401,13 @@ loop:
|
||||
goto loop;
|
||||
}
|
||||
if (ap->a_flags & FSYNC_WAIT) {
|
||||
simple_lock(&global_v_numoutput_slock);
|
||||
while (vp->v_numoutput) {
|
||||
vp->v_flag |= VBWAIT;
|
||||
(void) tsleep(&vp->v_numoutput, PRIBIO + 1,
|
||||
"ffsfsync", 0);
|
||||
(void) ltsleep(&vp->v_numoutput, PRIBIO + 1,
|
||||
"ffsfsync", 0, &global_v_numoutput_slock);
|
||||
}
|
||||
simple_unlock(&global_v_numoutput_slock);
|
||||
splx(s);
|
||||
|
||||
if (ap->a_flags & FSYNC_DATAONLY)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lfs_bio.c,v 1.56 2003/01/24 21:55:26 fvdl Exp $ */
|
||||
/* $NetBSD: lfs_bio.c,v 1.57 2003/02/05 21:38:45 pk Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -71,7 +71,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.56 2003/01/24 21:55:26 fvdl Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.57 2003/02/05 21:38:45 pk Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -641,10 +641,11 @@ lfs_newbuf(struct lfs *fs, struct vnode *vp, daddr_t daddr, size_t size)
|
||||
if (bp == NULL)
|
||||
panic("bp is NULL after malloc in lfs_newbuf");
|
||||
#endif
|
||||
simple_lock_init(&bp->b_interlock);
|
||||
s = splbio();
|
||||
bgetvp(vp, bp);
|
||||
splx(s);
|
||||
|
||||
|
||||
bp->b_saveaddr = (caddr_t)fs;
|
||||
bp->b_bufsize = size;
|
||||
bp->b_bcount = size;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lfs_segment.c,v 1.99 2003/02/01 06:23:53 thorpej Exp $ */
|
||||
/* $NetBSD: lfs_segment.c,v 1.100 2003/02/05 21:38:45 pk Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -71,7 +71,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.99 2003/02/01 06:23:53 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.100 2003/02/05 21:38:45 pk Exp $");
|
||||
|
||||
#define ivndebug(vp,str) printf("ino %d: %s\n",VTOI(vp)->i_number,(str))
|
||||
|
||||
@ -1492,6 +1492,7 @@ lookahead_pagemove(struct buf **bpp, int nblocks, size_t *size)
|
||||
#define BQUEUES 4 /* XXX */
|
||||
#define BQ_EMPTY 3 /* XXX */
|
||||
extern TAILQ_HEAD(bqueues, buf) bufqueues[BQUEUES];
|
||||
extern struct simplelock bqueue_slock;
|
||||
|
||||
#define BUFHASH(dvp, lbn) \
|
||||
(&bufhashtbl[((long)(dvp) / sizeof(*(dvp)) + (int)(lbn)) & bufhash])
|
||||
@ -1527,7 +1528,9 @@ lfs_newclusterbuf(struct lfs *fs, struct vnode *vp, daddr_t addr, int n)
|
||||
|
||||
/* Get an empty buffer header, or maybe one with something on it */
|
||||
s = splbio();
|
||||
simple_lock(&bqueue_slock);
|
||||
if((bp = bufqueues[BQ_EMPTY].tqh_first) != NULL) {
|
||||
simple_lock(&bp->b_interlock);
|
||||
bremfree(bp);
|
||||
/* clear out various other fields */
|
||||
bp->b_flags = B_BUSY;
|
||||
@ -1546,12 +1549,12 @@ lfs_newclusterbuf(struct lfs *fs, struct vnode *vp, daddr_t addr, int n)
|
||||
if (bp->b_vp)
|
||||
brelvp(bp);
|
||||
}
|
||||
splx(s);
|
||||
while (!bp)
|
||||
bp = getnewbuf(0, 0);
|
||||
s = splbio();
|
||||
bgetvp(vp, bp);
|
||||
binshash(bp,&invalhash);
|
||||
simple_unlock(&bp->b_interlock);
|
||||
simple_unlock(&bqueue_slock);
|
||||
splx(s);
|
||||
bp->b_bcount = 0;
|
||||
bp->b_blkno = bp->b_lblkno = addr;
|
||||
@ -1917,7 +1920,7 @@ lfs_writeseg(struct lfs *fs, struct segment *sp)
|
||||
cl->bpp[cl->bufcount++] = bp;
|
||||
vp = bp->b_vp;
|
||||
s = splbio();
|
||||
++vp->v_numoutput;
|
||||
V_INCR_NUMOUTPUT(vp);
|
||||
splx(s);
|
||||
|
||||
/*
|
||||
@ -1972,7 +1975,7 @@ lfs_writeseg(struct lfs *fs, struct segment *sp)
|
||||
wakeup(vp);
|
||||
}
|
||||
s = splbio();
|
||||
++cbp->b_vp->v_numoutput;
|
||||
V_INCR_NUMOUTPUT(cbp->b_vp);
|
||||
splx(s);
|
||||
/*
|
||||
* In order to include the summary in a clustered block,
|
||||
@ -2046,7 +2049,7 @@ lfs_writesuper(struct lfs *fs, daddr_t daddr)
|
||||
vop_strategy_a.a_desc = VDESC(vop_strategy);
|
||||
vop_strategy_a.a_bp = bp;
|
||||
s = splbio();
|
||||
++bp->b_vp->v_numoutput;
|
||||
V_INCR_NUMOUTPUT(bp->b_vp);
|
||||
splx(s);
|
||||
++fs->lfs_iocount;
|
||||
(strategy)(&vop_strategy_a);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: uvm_swap.c,v 1.75 2003/02/01 06:23:55 thorpej Exp $ */
|
||||
/* $NetBSD: uvm_swap.c,v 1.76 2003/02/05 21:38:46 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995, 1996, 1997 Matthew R. Green
|
||||
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_swap.c,v 1.75 2003/02/01 06:23:55 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_swap.c,v 1.76 2003/02/05 21:38:46 pk Exp $");
|
||||
|
||||
#include "fs_nfs.h"
|
||||
#include "opt_uvmhist.h"
|
||||
@ -1168,7 +1168,7 @@ swstrategy(bp)
|
||||
*/
|
||||
if ((bp->b_flags & B_READ) == 0) {
|
||||
vwakeup(bp); /* kills one 'v_numoutput' on drum */
|
||||
vp->v_numoutput++; /* put it on swapdev */
|
||||
V_INCR_NUMOUTPUT(vp); /* put it on swapdev */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1286,6 +1286,7 @@ sw_reg_strategy(sdp, bp, bn)
|
||||
* cast pointers between the two structure easily.
|
||||
*/
|
||||
getvndbuf(nbp);
|
||||
simple_lock_init(&nbp->vb_buf.b_interlock);
|
||||
nbp->vb_buf.b_flags = bp->b_flags | B_CALL;
|
||||
nbp->vb_buf.b_bcount = sz;
|
||||
nbp->vb_buf.b_bufsize = sz;
|
||||
@ -1368,7 +1369,7 @@ sw_reg_start(sdp)
|
||||
"sw_reg_start: bp %p vp %p blkno %p cnt %lx",
|
||||
bp, bp->b_vp, bp->b_blkno, bp->b_bcount);
|
||||
if ((bp->b_flags & B_READ) == 0)
|
||||
bp->b_vp->v_numoutput++;
|
||||
V_INCR_NUMOUTPUT(bp->b_vp);
|
||||
|
||||
VOP_STRATEGY(bp);
|
||||
}
|
||||
@ -1698,6 +1699,7 @@ uvm_swap_io(pps, startslot, npages, flags)
|
||||
* /dev/drum's vnode [swapdev_vp].
|
||||
*/
|
||||
|
||||
simple_lock_init(&bp->b_interlock);
|
||||
bp->b_flags = B_BUSY | B_NOCACHE | (flags & (B_READ|B_ASYNC));
|
||||
bp->b_proc = &proc0; /* XXX */
|
||||
bp->b_vnbufs.le_next = NOLIST;
|
||||
@ -1714,7 +1716,7 @@ uvm_swap_io(pps, startslot, npages, flags)
|
||||
|
||||
if (write) {
|
||||
s = splbio();
|
||||
swapdev_vp->v_numoutput++;
|
||||
V_INCR_NUMOUTPUT(swapdev_vp);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user