diff options
author | phk <phk@FreeBSD.org> | 2004-03-11 18:50:33 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2004-03-11 18:50:33 +0000 |
commit | 5c532f7fd4286a2a53b4ac3a8381da5b89251557 (patch) | |
tree | 2b5985795bbbb2d7db3118632ad579bf98d8f94a | |
parent | 265fe61be82dff80c5b876620d07c8a8edcf4c25 (diff) | |
download | FreeBSD-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.c | 20 | ||||
-rw-r--r-- | sys/kern/vfs_bio.c | 8 | ||||
-rw-r--r-- | sys/sys/buf.h | 10 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_softdep.c | 30 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 3 |
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); } |