diff options
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/fdescfs/fdesc_vnops.c | 9 | ||||
-rw-r--r-- | sys/fs/fifofs/fifo_vnops.c | 1 | ||||
-rw-r--r-- | sys/fs/specfs/spec_vnops.c | 22 | ||||
-rw-r--r-- | sys/fs/unionfs/union_subr.c | 30 | ||||
-rw-r--r-- | sys/fs/unionfs/union_vnops.c | 16 |
5 files changed, 66 insertions, 12 deletions
diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c index 772a94c..72c7cae 100644 --- a/sys/fs/fdescfs/fdesc_vnops.c +++ b/sys/fs/fdescfs/fdesc_vnops.c @@ -383,6 +383,8 @@ fdesc_setattr(ap) { struct filedesc *fdp = ap->a_p->p_fd; struct vattr *vap = ap->a_vap; + struct vnode *vp; + struct mount *mp; struct file *fp; unsigned fd; int error; @@ -403,8 +405,11 @@ fdesc_setattr(ap) switch (fp->f_type) { case DTYPE_FIFO: case DTYPE_VNODE: - error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, - ap->a_cred, ap->a_p); + vp = (struct vnode *)fp->f_data; + if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) + return (error); + error = VOP_SETATTR(vp, ap->a_vap, ap->a_cred, ap->a_p); + vn_finished_write(mp); break; default: diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c index 5bd13a7..03e3e37 100644 --- a/sys/fs/fifofs/fifo_vnops.c +++ b/sys/fs/fifofs/fifo_vnops.c @@ -107,6 +107,7 @@ static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { { &vop_open_desc, (vop_t *) fifo_open }, { &vop_pathconf_desc, (vop_t *) fifo_pathconf }, { &vop_poll_desc, (vop_t *) fifo_poll }, + { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount }, { &vop_print_desc, (vop_t *) fifo_print }, { &vop_read_desc, (vop_t *) fifo_read }, { &vop_readdir_desc, (vop_t *) fifo_badop }, diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c index cbe52f4..baf40c3 100644 --- a/sys/fs/specfs/spec_vnops.c +++ b/sys/fs/specfs/spec_vnops.c @@ -88,6 +88,7 @@ static struct vnodeopv_entry_desc spec_vnodeop_entries[] = { { &vop_open_desc, (vop_t *) spec_open }, { &vop_pathconf_desc, (vop_t *) vop_stdpathconf }, { &vop_poll_desc, (vop_t *) spec_poll }, + { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount }, { &vop_print_desc, (vop_t *) spec_print }, { &vop_read_desc, (vop_t *) spec_read }, { &vop_readdir_desc, (vop_t *) vop_panic }, @@ -415,16 +416,29 @@ spec_strategy(ap) struct buf *bp; struct vnode *vp; struct mount *mp; + int error; bp = ap->a_bp; - if ((bp->b_iocmd == BIO_WRITE) && (LIST_FIRST(&bp->b_dep)) != NULL) - buf_start(bp); - + vp = ap->a_vp; + if ((bp->b_iocmd == BIO_WRITE)) { + if (vp->v_mount != NULL && + (vp->v_mount->mnt_kern_flag & MNTK_SUSPENDED) != 0) + panic("spec_strategy: bad I/O"); + if (LIST_FIRST(&bp->b_dep) != NULL) + buf_start(bp); + if ((vp->v_flag & VCOPYONWRITE) && + (error = VOP_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. */ - vp = ap->a_vp; if (vn_isdisk(vp, NULL) && (mp = vp->v_specmountpoint) != NULL) { if (bp->b_iocmd == BIO_WRITE) { if (bp->b_lock.lk_lockholder == LK_KERNPROC) diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c index 6b88bef..d1d6e31 100644 --- a/sys/fs/unionfs/union_subr.c +++ b/sys/fs/unionfs/union_subr.c @@ -747,6 +747,7 @@ union_copyup(un, docopy, cred, p) struct proc *p; { int error; + struct mount *mp; struct vnode *lvp, *uvp; /* @@ -759,9 +760,12 @@ union_copyup(un, docopy, cred, p) if (error) return (error); - error = union_vn_create(&uvp, un, p); - if (error) + if ((error = vn_start_write(un->un_dirvp, &mp, V_WAIT | PCATCH)) != 0) return (error); + if ((error = union_vn_create(&uvp, un, p)) != 0) { + vn_finished_write(mp); + return (error); + } lvp = un->un_lowervp; @@ -785,6 +789,7 @@ union_copyup(un, docopy, cred, p) } VOP_UNLOCK(uvp, 0, p); + vn_finished_write(mp); union_newupper(un, uvp); KASSERT(uvp->v_usecount > 0, ("copy: uvp refcount 0: %d", uvp->v_usecount)); union_vn_close(uvp, FWRITE, cred, p); @@ -910,11 +915,15 @@ union_mkshadow(um, dvp, cnp, vpp) struct vattr va; struct proc *p = cnp->cn_proc; struct componentname cn; + struct mount *mp; - error = union_relookup(um, dvp, vpp, cnp, &cn, - cnp->cn_nameptr, cnp->cn_namelen); - if (error) + if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH)) != 0) + return (error); + if ((error = union_relookup(um, dvp, vpp, cnp, &cn, + cnp->cn_nameptr, cnp->cn_namelen)) != 0) { + vn_finished_write(mp); return (error); + } if (*vpp) { if (cn.cn_flags & HASBUF) { @@ -925,6 +934,7 @@ union_mkshadow(um, dvp, cnp, vpp) vrele(*vpp); else vput(*vpp); + vn_finished_write(mp); *vpp = NULLVP; return (EEXIST); } @@ -950,6 +960,7 @@ union_mkshadow(um, dvp, cnp, vpp) cn.cn_flags &= ~HASBUF; } /*vput(dvp);*/ + vn_finished_write(mp); return (error); } @@ -973,10 +984,15 @@ union_mkwhiteout(um, dvp, cnp, path) struct proc *p = cnp->cn_proc; struct vnode *wvp; struct componentname cn; + struct mount *mp; + if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH)) != 0) + return (error); error = union_relookup(um, dvp, &wvp, cnp, &cn, path, strlen(path)); - if (error) + if (error) { + vn_finished_write(mp); return (error); + } if (wvp) { if (cn.cn_flags & HASBUF) { @@ -987,6 +1003,7 @@ union_mkwhiteout(um, dvp, cnp, path) vrele(wvp); else vput(wvp); + vn_finished_write(mp); return (EEXIST); } @@ -998,6 +1015,7 @@ union_mkwhiteout(um, dvp, cnp, path) zfree(namei_zone, cn.cn_pnbuf); cn.cn_flags &= ~HASBUF; } + vn_finished_write(mp); return (error); } diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index 1c5ed5d..d7b95f3 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -93,6 +93,7 @@ static int union_print __P((struct vop_print_args *ap)); static int union_read __P((struct vop_read_args *ap)); static int union_readdir __P((struct vop_readdir_args *ap)); static int union_readlink __P((struct vop_readlink_args *ap)); +static int union_getwritemount __P((struct vop_getwritemount_args *ap)); static int union_reclaim __P((struct vop_reclaim_args *ap)); static int union_remove __P((struct vop_remove_args *ap)); static int union_rename __P((struct vop_rename_args *ap)); @@ -1681,6 +1682,20 @@ union_readlink(ap) return (error); } +static int +union_getwritemount(ap) + struct vop_getwritemount_args /* { + struct vnode *a_vp; + struct mount **a_mpp; + } */ *ap; +{ + struct vnode *vp = UPPERVP(ap->a_vp); + + if (vp == NULL) + panic("union: missing upper layer in getwritemount"); + return(VOP_GETWRITEMOUNT(vp, ap->a_mpp)); +} + /* * union_inactive: * @@ -1963,6 +1978,7 @@ static struct vnodeopv_entry_desc union_vnodeop_entries[] = { { &vop_read_desc, (vop_t *) union_read }, { &vop_readdir_desc, (vop_t *) union_readdir }, { &vop_readlink_desc, (vop_t *) union_readlink }, + { &vop_getwritemount_desc, (vop_t *) union_getwritemount }, { &vop_reclaim_desc, (vop_t *) union_reclaim }, { &vop_remove_desc, (vop_t *) union_remove }, { &vop_rename_desc, (vop_t *) union_rename }, |