-/* kern_physio.c 4.3 %G% */
+/* kern_physio.c 4.5 %G% */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/seg.h"
#include "../h/pte.h"
#include "../h/vm.h"
+#include "../h/trace.h"
/*
* The following several routines allocate and free
bp = getblk(dev, blkno);
if (bp->b_flags&B_DONE) {
+#ifdef EPAWNJ
+ trace(TR_BREAD|TR_HIT, dev, blkno);
+#endif
#ifdef DISKMON
io_info.ncache++;
#endif
bp->b_flags |= B_READ;
bp->b_bcount = BSIZE;
(*bdevsw[major(dev)].d_strategy)(bp);
+#ifdef EPAWNJ
+ trace(TR_BREAD|TR_MISS, dev, blkno);
+#endif
#ifdef DISKMON
io_info.nread++;
#endif
bp->b_flags |= B_READ;
bp->b_bcount = BSIZE;
(*bdevsw[major(dev)].d_strategy)(bp);
+#ifdef EPAWNJ
+ trace(TR_BREAD|TR_MISS, dev, blkno);
+#endif
#ifdef DISKMON
io_info.nread++;
#endif
u.u_vm.vm_inblk++; /* pay for read */
}
+#ifdef EPAWNJ
+ else
+ trace(TR_BREAD|TR_HIT, dev, blkno);
+#endif
}
if (rablkno && !incore(dev, rablkno)) {
rabp = getblk(dev, rablkno);
- if (rabp->b_flags & B_DONE)
+ if (rabp->b_flags & B_DONE) {
brelse(rabp);
- else {
+#ifdef EPAWNJ
+ trace(TR_BREAD|TR_HIT|TR_RA, dev, blkno);
+#endif
+ } else {
rabp->b_flags |= B_READ|B_ASYNC;
rabp->b_bcount = BSIZE;
(*bdevsw[major(dev)].d_strategy)(rabp);
+#ifdef EPAWNJ
+ trace(TR_BREAD|TR_MISS|TR_RA, dev, rablock);
+#endif
#ifdef DISKMON
io_info.nreada++;
#endif
#endif
if ((flag&B_DELWRI) == 0)
u.u_vm.vm_oublk++; /* noone paid yet */
+#ifdef EPAWNJ
+ trace(TR_BWRITE, bp->b_dev, dbtofsb(bp->b_blkno));
+#endif
(*bdevsw[major(bp->b_dev)].d_strategy)(bp);
if ((flag&B_ASYNC) == 0) {
iowait(bp);
for (bp = &buf[bufhash[BUFHASH(blkno)]]; bp != &buf[-1];
bp = &buf[bp->b_hlink])
- if (bp->b_blkno == dblkno && bp->b_dev == dev)
+ if (bp->b_blkno == dblkno && bp->b_dev == dev
+ && !(bp->b_flags & B_INVAL))
return (1);
return (0);
}
(void) spl0();
for (bp = &buf[bufhash[BUFHASH(blkno)]]; bp != &buf[-1];
bp = &buf[bp->b_hlink]) {
- if (bp->b_blkno != dblkno || bp->b_dev != dev)
+ if (bp->b_blkno != dblkno || bp->b_dev != dev
+ || bp->b_flags & B_INVAL)
continue;
(void) spl6();
if (bp->b_flags&B_BUSY) {
if (bp->b_dev == NODEV)
goto done;
/* INLINE EXPANSION OF bunhash(bp) */
+#ifdef EPAWNJ
+ trace(TR_BRELSE, bp->b_dev, dbtofsb(bp->b_blkno));
+#endif
(void) spl6();
i = BUFHASH(dbtofsb(bp->b_blkno));
x = bp - buf;
bwrite(bp);
goto loop;
}
- if (bp->b_dev != NODEV)
+ if (bp->b_dev != NODEV) {
+#ifdef EPAWNJ
+ trace(TR_BRELSE, bp->b_dev, dbtofsb(bp->b_blkno));
+#endif
bunhash(bp);
+ }
bp->b_flags = B_BUSY;
bp->b_back->b_forw = bp->b_forw;
bp->b_forw->b_back = bp->b_back;
if ((u.u_error = bp->b_error)==0)
u.u_error = EIO;
}
+
+/*
+ * Invalidate in core blocks belonging to closed or umounted filesystem
+ *
+ * This is not nicely done at all - the buffer ought to be removed from the
+ * hash chains & have its dev/blkno fields clobbered, but unfortunately we
+ * can't do that here, as it is quite possible that the block is still
+ * being used for i/o. Eventually, all disc drivers should be forced to
+ * have a close routine, which ought ensure that the queue is empty, then
+ * properly flush the queues. Until that happy day, this suffices for
+ * correctness. ... kre
+ */
+binval(dev)
+dev_t dev;
+{
+ register struct buf *bp, *dp;
+
+ dp = bdevsw[major(dev)].d_tab;
+
+ for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
+ if (bp->b_dev == dev)
+ bp->b_flags |= B_INVAL;
+}