diff options
-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); } |