summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2004-03-11 18:50:33 +0000
committerphk <phk@FreeBSD.org>2004-03-11 18:50:33 +0000
commit5c532f7fd4286a2a53b4ac3a8381da5b89251557 (patch)
tree2b5985795bbbb2d7db3118632ad579bf98d8f94a
parent265fe61be82dff80c5b876620d07c8a8edcf4c25 (diff)
downloadFreeBSD-src-5c532f7fd4286a2a53b4ac3a8381da5b89251557.zip
FreeBSD-src-5c532f7fd4286a2a53b4ac3a8381da5b89251557.tar.gz
When I was a kid my work table was one cluttered mess an cleaning it up
were a rather overwhelming task. I soon learned that if you don't know where you're going to store something, at least try to pile it next to something slightly related in the hope that a pattern emerges. Apply the same principle to the ffs/snapshot/softupdates code which have leaked into specfs: Add yet a buf-quasi-method and call it from the only two places I can see it can make a difference and implement the magic in ffs_softdep.c where it belongs. It's not pretty, but at least it's one less layer violated.
-rw-r--r--sys/fs/specfs/spec_vnops.c20
-rw-r--r--sys/kern/vfs_bio.c8
-rw-r--r--sys/sys/buf.h10
-rw-r--r--sys/ufs/ffs/ffs_softdep.c30
-rw-r--r--sys/ufs/ufs/ufs_vnops.c3
5 files changed, 47 insertions, 24 deletions
diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c
index 97c3804..92094f0 100644
--- a/sys/fs/specfs/spec_vnops.c
+++ b/sys/fs/specfs/spec_vnops.c
@@ -463,7 +463,6 @@ static int
spec_xstrategy(struct vnode *vp, struct buf *bp)
{
struct mount *mp;
- int error;
struct cdevsw *dsw;
struct thread *td = curthread;
@@ -481,25 +480,6 @@ spec_xstrategy(struct vnode *vp, struct buf *bp)
PPAUSE | PCATCH | PDROP, "ioslow",
td->td_ksegrp->kg_nice);
}
- if (bp->b_iocmd == BIO_WRITE) {
- if ((bp->b_flags & B_VALIDSUSPWRT) == 0 &&
- bp->b_vp != NULL && bp->b_vp->v_mount != NULL &&
- (bp->b_vp->v_mount->mnt_kern_flag & MNTK_SUSPENDED) != 0)
- panic("spec_strategy: bad I/O");
- bp->b_flags &= ~B_VALIDSUSPWRT;
- if (LIST_FIRST(&bp->b_dep) != NULL)
- buf_start(bp);
- mp_fixme("This should require the vnode lock.");
- if ((vp->v_vflag & VV_COPYONWRITE) &&
- vp->v_rdev->si_copyonwrite &&
- (error = (*vp->v_rdev->si_copyonwrite)(vp, bp)) != 0 &&
- error != EOPNOTSUPP) {
- bp->b_io.bio_error = error;
- bp->b_io.bio_flags |= BIO_ERROR;
- biodone(&bp->b_io);
- return (0);
- }
- }
/*
* Collect statistics on synchronous and asynchronous read
* and write counts for disks that have associated filesystems.
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index bba9a55..d612fc9 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -886,10 +886,12 @@ ibwrite(struct buf * bp)
if (oldflags & B_ASYNC)
BUF_KERNPROC(bp);
bp->b_iooffset = dbtob(bp->b_blkno);
- if (bp->b_vp->v_type == VCHR)
- VOP_SPECSTRATEGY(bp->b_vp, bp);
- else
+ if (bp->b_vp->v_type == VCHR) {
+ if (!buf_prewrite(bp->b_vp, bp))
+ VOP_SPECSTRATEGY(bp->b_vp, bp);
+ } else {
VOP_STRATEGY(bp->b_vp, bp);
+ }
if ((oldflags & B_ASYNC) == 0) {
int rtval = bufwait(bp);
diff --git a/sys/sys/buf.h b/sys/sys/buf.h
index 7aeda2a..ce4744f 100644
--- a/sys/sys/buf.h
+++ b/sys/sys/buf.h
@@ -62,6 +62,7 @@ LIST_HEAD(workhead, worklist);
* to each buffer.
*/
extern struct bio_ops {
+ int (*io_prewrite)(struct vnode *, struct buf *);
void (*io_start)(struct buf *);
void (*io_complete)(struct buf *);
void (*io_deallocate)(struct buf *);
@@ -404,6 +405,15 @@ struct cluster_save {
#ifdef _KERNEL
+static __inline int
+buf_prewrite(struct vnode *vp, struct buf *bp)
+{
+ if (bioops.io_start)
+ return (*bioops.io_prewrite)(vp, bp);
+ else
+ return (0);
+}
+
static __inline void
buf_start(struct buf *bp)
{
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 2649545..10be8b2 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -202,6 +202,7 @@ static void add_to_worklist(struct worklist *);
/*
* Exported softdep operations.
*/
+static int softdep_disk_prewrite(struct vnode *vp, struct buf *bp);
static void softdep_disk_io_initiation(struct buf *);
static void softdep_disk_write_complete(struct buf *);
static void softdep_deallocate_dependencies(struct buf *);
@@ -1152,6 +1153,7 @@ softdep_initialize()
softdep_fsync_hook = softdep_fsync;
/* initialise bioops hack */
+ bioops.io_prewrite = softdep_disk_prewrite;
bioops.io_start = softdep_disk_io_initiation;
bioops.io_complete = softdep_disk_write_complete;
bioops.io_deallocate = softdep_deallocate_dependencies;
@@ -3413,6 +3415,34 @@ handle_workitem_freefile(freefile)
WORKITEM_FREE(freefile, D_FREEFILE);
}
+static int
+softdep_disk_prewrite(struct vnode *vp, struct buf *bp)
+{
+ int error;
+
+ if (bp->b_iocmd != BIO_WRITE)
+ return (0);
+ if ((bp->b_flags & B_VALIDSUSPWRT) == 0 &&
+ bp->b_vp != NULL && bp->b_vp->v_mount != NULL &&
+ (vp->v_mount->mnt_kern_flag & MNTK_SUSPENDED) != 0)
+ panic("softdep_disk_prewrite: bad I/O");
+ bp->b_flags &= ~B_VALIDSUSPWRT;
+ if (LIST_FIRST(&bp->b_dep) != NULL)
+ buf_start(bp);
+ mp_fixme("This should require the vnode lock.");
+ if ((vp->v_vflag & VV_COPYONWRITE) &&
+ vp->v_rdev->si_copyonwrite &&
+ (error = (*vp->v_rdev->si_copyonwrite)(vp, bp)) != 0 &&
+ error != EOPNOTSUPP) {
+ bp->b_io.bio_error = error;
+ bp->b_io.bio_flags |= BIO_ERROR;
+ biodone(&bp->b_io);
+ return (1);
+ }
+ return (0);
+}
+
+
/*
* Disk writes.
*
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index b43c6b3..32c5a27 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -1971,7 +1971,8 @@ ufs_strategy(ap)
vp = ip->i_devvp;
bp->b_dev = vp->v_rdev;
bp->b_iooffset = dbtob(bp->b_blkno);
- VOP_SPECSTRATEGY(vp, bp);
+ if (!buf_prewrite(vp, bp))
+ VOP_SPECSTRATEGY(vp, bp);
return (0);
}
OpenPOWER on IntegriCloud