aboutsummaryrefslogtreecommitdiff
path: root/sys/fs/nullfs
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2012-11-02 13:56:36 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2012-11-02 13:56:36 +0000
commit140dedb81c5bee09f8bc21997b990f4f96192ce7 (patch)
tree77eb9f8e9de108d0ae7792cfceedcd340198177e /sys/fs/nullfs
parentcd463097e966f4b968964c7de2c34d9ebe8d5226 (diff)
downloadsrc-140dedb81c5bee09f8bc21997b990f4f96192ce7.tar.gz
src-140dedb81c5bee09f8bc21997b990f4f96192ce7.zip
The r241025 fixed the case when a binary, executed from nullfs mount,
was still possible to open for write from the lower filesystem. There is a symmetric situation where the binary could already has file descriptors opened for write, but it can be executed from the nullfs overlay. Handle the issue by passing one v_writecount reference to the lower vnode if nullfs vnode has non-zero v_writecount. Note that only one write reference can be donated, since nullfs only keeps one use reference on the lower vnode. Always use the lower vnode v_writecount for the checks. Introduce the VOP_GET_WRITECOUNT to read v_writecount, which is currently always bypassed to the lower vnode, and VOP_ADD_WRITECOUNT to manipulate the v_writecount value, which manages a single bypass reference to the lower vnode. Caling the VOPs instead of directly accessing v_writecount provide the fix described in the previous paragraph. Tested by: pho MFC after: 3 weeks
Notes
Notes: svn path=/head/; revision=242476
Diffstat (limited to 'sys/fs/nullfs')
-rw-r--r--sys/fs/nullfs/null_vnops.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index 94bfea803979..f530ed217f2f 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -329,6 +329,26 @@ null_bypass(struct vop_generic_args *ap)
return (error);
}
+static int
+null_add_writecount(struct vop_add_writecount_args *ap)
+{
+ struct vnode *lvp, *vp;
+ int error;
+
+ vp = ap->a_vp;
+ lvp = NULLVPTOLOWERVP(vp);
+ KASSERT(vp->v_writecount + ap->a_inc >= 0, ("wrong writecount inc"));
+ if (vp->v_writecount > 0 && vp->v_writecount + ap->a_inc == 0)
+ error = VOP_ADD_WRITECOUNT(lvp, -1);
+ else if (vp->v_writecount == 0 && vp->v_writecount + ap->a_inc > 0)
+ error = VOP_ADD_WRITECOUNT(lvp, 1);
+ else
+ error = 0;
+ if (error == 0)
+ vp->v_writecount += ap->a_inc;
+ return (error);
+}
+
/*
* We have to carry on the locking protocol on the null layer vnodes
* as we progress through the tree. We also have to enforce read-only
@@ -826,4 +846,5 @@ struct vop_vector null_vnodeops = {
.vop_unlock = null_unlock,
.vop_vptocnp = null_vptocnp,
.vop_vptofh = null_vptofh,
+ .vop_add_writecount = null_add_writecount,
};