summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_bio.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r--sys/kern/vfs_bio.c78
1 files changed, 77 insertions, 1 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 4c09e1d..114e035 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -11,7 +11,7 @@
* 2. Absolutely no warranty of function or purpose is made by the author
* John S. Dyson.
*
- * $Id: vfs_bio.c,v 1.153 1998/03/04 03:17:30 dyson Exp $
+ * $Id: vfs_bio.c,v 1.154 1998/03/07 21:35:24 dyson Exp $
*/
/*
@@ -37,6 +37,7 @@
#include <sys/vnode.h>
#include <sys/vmmeter.h>
#include <sys/lock.h>
+#include <miscfs/specfs/specdev.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
@@ -53,6 +54,9 @@
static MALLOC_DEFINE(M_BIOBUF, "BIO buffer", "BIO buffer");
+struct bio_ops bioops; /* I/O operation notification */
+
+#if 0 /* replaced bu sched_sync */
static void vfs_update __P((void));
static struct proc *updateproc;
static struct kproc_desc up_kp = {
@@ -61,6 +65,7 @@ static struct kproc_desc up_kp = {
&updateproc
};
SYSINIT_KT(update, SI_SUB_KTHREAD_UPDATE, SI_ORDER_FIRST, kproc_start, &up_kp)
+#endif
struct buf *buf; /* buffer header pool */
struct swqueue bswlist;
@@ -179,6 +184,7 @@ bufinit()
bp->b_qindex = QUEUE_EMPTY;
bp->b_vnbufs.le_next = NOLIST;
bp->b_generation = 0;
+ LIST_INIT(&bp->b_dep);
TAILQ_INSERT_TAIL(&bufqueues[QUEUE_EMPTY], bp, b_freelist);
LIST_INSERT_HEAD(&invalhash, bp, b_hash);
}
@@ -362,6 +368,9 @@ int
bwrite(struct buf * bp)
{
int oldflags = bp->b_flags;
+ struct vnode *vp;
+ struct mount *mp;
+
if (bp->b_flags & B_INVAL) {
brelse(bp);
@@ -386,6 +395,23 @@ bwrite(struct buf * bp)
curproc->p_stats->p_ru.ru_oublock++;
VOP_STRATEGY(bp);
+ /*
+ * Collect statistics on synchronous and asynchronous writes.
+ * Writes to block devices are charged to their associated
+ * filesystem (if any).
+ */
+ if ((vp = bp->b_vp) != NULL) {
+ if (vp->v_type == VBLK)
+ mp = vp->v_specmountpoint;
+ else
+ mp = vp->v_mount;
+ if (mp != NULL)
+ if ((oldflags & B_ASYNC) == 0)
+ mp->mnt_stat.f_syncwrites++;
+ else
+ mp->mnt_stat.f_asyncwrites++;
+ }
+
if ((oldflags & B_ASYNC) == 0) {
int rtval = biowait(bp);
@@ -420,6 +446,8 @@ vfs_bio_need_satisfy(void) {
void
bdwrite(struct buf * bp)
{
+ int s;
+ struct vnode *vp;
#if !defined(MAX_PERF)
if ((bp->b_flags & B_BUSY) == 0) {
@@ -438,7 +466,9 @@ bdwrite(struct buf * bp)
bp->b_flags &= ~(B_READ|B_RELBUF);
if ((bp->b_flags & B_DELWRI) == 0) {
bp->b_flags |= B_DONE | B_DELWRI;
+ s = splbio();
reassignbuf(bp, bp->b_vp);
+ splx(s);
++numdirtybuffers;
}
@@ -470,12 +500,45 @@ bdwrite(struct buf * bp)
vfs_clean_pages(bp);
bqrelse(bp);
+ /*
+ * XXX The soft dependency code is not prepared to
+ * have I/O done when a bdwrite is requested. For
+ * now we just let the write be delayed if it is
+ * requested by the soft dependency code.
+ */
+ if ((vp = bp->b_vp) &&
+ (vp->v_type == VBLK && vp->v_specmountpoint &&
+ (vp->v_specmountpoint->mnt_flag & MNT_SOFTDEP)) ||
+ (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)))
+ return;
+
if (numdirtybuffers >= hidirtybuffers)
flushdirtybuffers(0, 0);
return;
}
+
+/*
+ * Same as first half of bdwrite, mark buffer dirty, but do not release it.
+ * Check how this compares with vfs_setdirty(); XXX [JRE]
+ */
+void
+bdirty(bp)
+ struct buf *bp;
+{
+ int s;
+
+ bp->b_flags &= ~(B_READ|B_RELBUF); /* XXX ??? check this */
+ if ((bp->b_flags & B_DELWRI) == 0) {
+ bp->b_flags |= B_DONE | B_DELWRI; /* why done? XXX JRE */
+ s = splbio();
+ reassignbuf(bp, bp->b_vp);
+ splx(s);
+ ++numdirtybuffers;
+ }
+}
+
/*
* Asynchronous write.
* Start output on a buffer, but do not wait for it to complete.
@@ -535,6 +598,8 @@ brelse(struct buf * bp)
if ((bp->b_flags & (B_NOCACHE | B_INVAL | B_ERROR)) ||
(bp->b_bufsize <= 0)) {
bp->b_flags |= B_INVAL;
+ if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_deallocate)
+ (*bioops.io_deallocate)(bp);
if (bp->b_flags & B_DELWRI)
--numdirtybuffers;
bp->b_flags &= ~(B_DELWRI | B_CACHE);
@@ -1065,6 +1130,9 @@ fillbuf:
crfree(bp->b_wcred);
bp->b_wcred = NOCRED;
}
+ if (LIST_FIRST(&bp->b_dep) != NULL &&
+ bioops.io_deallocate)
+ (*bioops.io_deallocate)(bp);
LIST_REMOVE(bp, b_hash);
LIST_INSERT_HEAD(&invalhash, bp, b_hash);
@@ -1083,6 +1151,8 @@ fillbuf:
bp->b_dirtyoff = bp->b_dirtyend = 0;
bp->b_validoff = bp->b_validend = 0;
bp->b_usecount = 5;
+ /* Here, not kern_physio.c, is where this should be done*/
+ LIST_INIT(&bp->b_dep);
maxsize = (maxsize + PAGE_MASK) & ~PAGE_MASK;
@@ -1799,6 +1869,9 @@ biodone(register struct buf * bp)
splx(s);
return;
}
+ if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_complete)
+ (*bioops.io_complete)(bp);
+
if (bp->b_flags & B_VMIO) {
int i, resid;
vm_ooffset_t foff;
@@ -1944,6 +2017,7 @@ count_lock_queue()
return (count);
}
+#if 0 /* not with kirks code */
static int vfs_update_interval = 30;
static void
@@ -1970,6 +2044,8 @@ sysctl_kern_updateinterval SYSCTL_HANDLER_ARGS
SYSCTL_PROC(_kern, KERN_UPDATEINTERVAL, update, CTLTYPE_INT|CTLFLAG_RW,
&vfs_update_interval, 0, sysctl_kern_updateinterval, "I", "");
+#endif
+
/*
* This routine is called in lieu of iodone in the case of
OpenPOWER on IntegriCloud