summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/fdescfs/fdesc_vnops.c9
-rw-r--r--sys/fs/fifofs/fifo_vnops.c1
-rw-r--r--sys/fs/specfs/spec_vnops.c22
-rw-r--r--sys/fs/unionfs/union_subr.c30
-rw-r--r--sys/fs/unionfs/union_vnops.c16
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 },
OpenPOWER on IntegriCloud