Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F168971568
D31917.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D31917.diff
View Options
diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c
--- a/sys/fs/unionfs/union_subr.c
+++ b/sys/fs/unionfs/union_subr.c
@@ -243,6 +243,49 @@
VI_UNLOCK(dvp);
}
+/*
+ * Common cleanup handling for unionfs_nodeget
+ * Upper, lower, and parent directory vnodes are expected to be referenced by
+ * the caller. Upper and lower vnodes, if non-NULL, are also expected to be
+ * exclusively locked by the caller.
+ * This function will return with the caller's locks and references undone.
+ */
+static void
+unionfs_nodeget_cleanup(struct vnode *vp, void *arg)
+{
+ struct unionfs_node *unp;
+
+ /*
+ * Lock and reset the default vnode lock; vgone() expects a locked
+ * vnode, and we're going to reset the vnode ops.
+ */
+ lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL);
+
+ /*
+ * Clear out private data and reset the vnode ops to avoid use of
+ * unionfs vnode ops on a partially constructed vnode.
+ */
+ VI_LOCK(vp);
+ vp->v_data = NULL;
+ vp->v_vnlock = &vp->v_lock;
+ vp->v_op = &dead_vnodeops;
+ VI_UNLOCK(vp);
+ vgone(vp);
+ vput(vp);
+
+ unp = arg;
+ if (unp->un_dvp != NULLVP)
+ vrele(unp->un_dvp);
+ if (unp->un_uppervp != NULLVP)
+ vput(unp->un_uppervp);
+ if (unp->un_lowervp != NULLVP)
+ vput(unp->un_lowervp);
+ if (unp->un_hashtbl != NULL)
+ hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, unp->un_hashmask);
+ free(unp->un_path, M_UNIONFSPATH);
+ free(unp, M_UNIONFSNODE);
+}
+
/*
* Make a new or get existing unionfs node.
*
@@ -263,6 +306,7 @@
int lkflags;
enum vtype vt;
+ error = 0;
ump = MOUNTTOUNIONFSMOUNT(mp);
lkflags = (cnp ? cnp->cn_lkflags : 0);
path = (cnp ? cnp->cn_nameptr : NULL);
@@ -301,11 +345,6 @@
free(unp, M_UNIONFSNODE);
return (error);
}
- error = insmntque(vp, mp); /* XXX: Too early for mpsafe fs */
- if (error != 0) {
- free(unp, M_UNIONFSNODE);
- return (error);
- }
if (dvp != NULLVP)
vref(dvp);
if (uppervp != NULLVP)
@@ -340,24 +379,35 @@
(lowervp != NULLVP && ump->um_lowervp == lowervp))
vp->v_vflag |= VV_ROOT;
+ vn_lock_pair(lowervp, false, uppervp, false);
+ error = insmntque1(vp, mp, unionfs_nodeget_cleanup, unp);
+ if (error != 0)
+ return (error);
+ if (lowervp != NULL && VN_IS_DOOMED(lowervp)) {
+ vput(lowervp);
+ unp->un_lowervp = NULL;
+ }
+ if (uppervp != NULL && VN_IS_DOOMED(uppervp)) {
+ vput(uppervp);
+ unp->un_uppervp = NULL;
+ }
+ if (unp->un_lowervp == NULL && unp->un_uppervp == NULL) {
+ unionfs_nodeget_cleanup(vp, unp);
+ return (ENOENT);
+ }
if (path != NULL && dvp != NULLVP && vt == VDIR)
*vpp = unionfs_ins_cached_vnode(unp, dvp, path);
- if ((*vpp) != NULLVP) {
- if (dvp != NULLVP)
- vrele(dvp);
- if (uppervp != NULLVP)
- vrele(uppervp);
- if (lowervp != NULLVP)
- vrele(lowervp);
-
- unp->un_uppervp = NULLVP;
- unp->un_lowervp = NULLVP;
- unp->un_dvp = NULLVP;
- vrele(vp);
+ if (*vpp != NULLVP) {
+ unionfs_nodeget_cleanup(vp, unp);
vp = *vpp;
vref(vp);
- } else
+ } else {
+ if (uppervp != NULL)
+ VOP_UNLOCK(uppervp);
+ if (lowervp != NULL)
+ VOP_UNLOCK(lowervp);
*vpp = vp;
+ }
unionfs_nodeget_out:
if (lkflags & LK_TYPE_MASK)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Sep 1, 12:37 AM (7 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37667190
Default Alt Text
D31917.diff (3 KB)
Attached To
Mode
D31917: unionfs: lock newly-created vnodes before calling insmntque()
Attached
Detach File
Event Timeline
Log In to Comment