FreeBSD Bugzilla – Attachment 248162 Details for
Bug 275871
[unionfs] [nullfs] [zfs] corrupt filesystem
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Implement VOP_UNP_* for unionfs
patch_unionfs_unp_stable (text/plain), 6.70 KB, created by
Jason A. Harmening
on 2024-02-03 18:51:01 UTC
(
hide
)
Description:
Implement VOP_UNP_* for unionfs
Filename:
MIME Type:
Creator:
Jason A. Harmening
Created:
2024-02-03 18:51:01 UTC
Size:
6.70 KB
patch
obsolete
>diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c >index ab277c685e41..966d8ae7bbea 100644 >--- a/sys/fs/unionfs/union_vnops.c >+++ b/sys/fs/unionfs/union_vnops.c >@@ -300,27 +300,8 @@ unionfs_lookup(struct vop_cachedlookup_args *ap) > error = lerror; > if (error != 0) > goto unionfs_lookup_cleanup; >- /* >- * get socket vnode. >- */ >- if (uvp != NULLVP && uvp->v_type == VSOCK) { >- vp = uvp; >- vref(vp); >- if (cnp->cn_lkflags & LK_TYPE_MASK) >- vn_lock(vp, cnp->cn_lkflags | LK_RETRY); >- } >- else if (lvp != NULLVP && lvp->v_type == VSOCK) { >- vp = lvp; >- vref(vp); >- if (cnp->cn_lkflags & LK_TYPE_MASK) >- vn_lock(vp, cnp->cn_lkflags | LK_RETRY); >- } >- /* >- * get unionfs vnode. >- */ >- else >- error = unionfs_nodeget(dvp->v_mount, uvp, lvp, >- dvp, &vp, cnp); >+ error = unionfs_nodeget(dvp->v_mount, uvp, lvp, >+ dvp, &vp, cnp); > if (error != 0) { > UNIONFSDEBUG( > "unionfs_lookup: Unable to create unionfs vnode."); >@@ -333,7 +314,7 @@ unionfs_lookup(struct vop_cachedlookup_args *ap) > > *(ap->a_vpp) = vp; > >- if ((cnflags & MAKEENTRY) && vp->v_type != VSOCK) >+ if (cnflags & MAKEENTRY) > cache_enter(dvp, vp, cnp); > > unionfs_lookup_cleanup: >@@ -375,14 +356,10 @@ unionfs_create(struct vop_create_args *ap) > if (error != 0) > goto unionfs_create_abort; > >- if (vp->v_type == VSOCK) >- *(ap->a_vpp) = vp; >- else { >- VOP_UNLOCK(vp); >- error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, >- ap->a_dvp, ap->a_vpp, cnp); >- vrele(vp); >- } >+ VOP_UNLOCK(vp); >+ error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, >+ ap->a_dvp, ap->a_vpp, cnp); >+ vrele(vp); > } > > unionfs_create_abort: >@@ -449,14 +426,10 @@ unionfs_mknod(struct vop_mknod_args *ap) > if (error != 0) > goto unionfs_mknod_abort; > >- if (vp->v_type == VSOCK) >- *(ap->a_vpp) = vp; >- else { >- VOP_UNLOCK(vp); >- error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, >- ap->a_dvp, ap->a_vpp, cnp); >- vrele(vp); >- } >+ VOP_UNLOCK(vp); >+ error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, >+ ap->a_dvp, ap->a_vpp, cnp); >+ vrele(vp); > } > > unionfs_mknod_abort: >@@ -1024,9 +997,7 @@ unionfs_remove(struct vop_remove_args *ap) > struct vnode *udvp; > struct vnode *uvp; > struct vnode *lvp; >- struct vnode *vp; > struct componentname *cnp; >- struct componentname cn; > struct thread *td; > int error; > int pathlen; >@@ -1041,54 +1012,17 @@ unionfs_remove(struct vop_remove_args *ap) > cnp = ap->a_cnp; > td = curthread; > >- if (ap->a_vp->v_op != &unionfs_vnodeops) { >- if (ap->a_vp->v_type != VSOCK) >- return (EINVAL); >- ump = NULL; >- vp = uvp = lvp = NULLVP; >- /* search vnode */ >- VOP_UNLOCK(ap->a_vp); >- error = unionfs_relookup(udvp, &vp, cnp, &cn, td, >- cnp->cn_nameptr, cnp->cn_namelen, DELETE); >- if (error != 0 && error != ENOENT) { >- vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); >- return (error); >- } >- >- if (error == 0 && vp == ap->a_vp) { >- /* target vnode in upper */ >- uvp = vp; >- vrele(vp); >- } else { >- /* target vnode in lower */ >- if (vp != NULLVP) { >- if (udvp == vp) >- vrele(vp); >- else >- vput(vp); >- } >- vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); >- lvp = ap->a_vp; >- } >- path = cnp->cn_nameptr; >- pathlen = cnp->cn_namelen; >- } else { >- ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); >- unp = VTOUNIONFS(ap->a_vp); >- uvp = unp->un_uppervp; >- lvp = unp->un_lowervp; >- path = unp->un_path; >- pathlen = unp->un_pathlen; >- } >+ ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); >+ unp = VTOUNIONFS(ap->a_vp); >+ uvp = unp->un_uppervp; >+ lvp = unp->un_lowervp; >+ path = unp->un_path; >+ pathlen = unp->un_pathlen; > > if (udvp == NULLVP) > return (EROFS); > > if (uvp != NULLVP) { >- /* >- * XXX: if the vnode type is VSOCK, it will create whiteout >- * after remove. >- */ > if (ump == NULL || ump->um_whitemode == UNIONFS_WHITE_ALWAYS || > lvp != NULLVP) > cnp->cn_flags |= DOWHITEOUT; >@@ -2777,6 +2711,64 @@ unionfs_unset_text(struct vop_unset_text_args *ap) > return (0); > } > >+static int >+unionfs_unp_bind(struct vop_unp_bind_args *ap) >+{ >+ struct vnode *tvp; >+ struct unionfs_node *unp; >+ >+ ASSERT_VOP_LOCKED(ap->a_vp, __func__); >+ unp = VTOUNIONFS(ap->a_vp); >+ tvp = unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp; >+ VOP_UNP_BIND(tvp, ap->a_unpcb); >+ return (0); >+} >+ >+static int >+unionfs_unp_connect(struct vop_unp_connect_args *ap) >+{ >+ struct vnode *tvp; >+ struct unionfs_node *unp; >+ >+ ASSERT_VOP_LOCKED(ap->a_vp, __func__); >+ unp = VTOUNIONFS(ap->a_vp); >+ tvp = unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp; >+ VOP_UNP_CONNECT(tvp, ap->a_unpcb); >+ return (0); >+} >+ >+static int >+unionfs_unp_detach(struct vop_unp_detach_args *ap) >+{ >+ struct vnode *tvp; >+ struct unionfs_node *unp; >+ >+ tvp = NULL; >+ /* >+ * VOP_UNP_DETACH() is not guaranteed to be called with the unionfs >+ * vnode locked, so we take the interlock to prevent a concurrent >+ * unmount from freeing the unionfs private data. >+ */ >+ VI_LOCK(ap->a_vp); >+ unp = VTOUNIONFS(ap->a_vp); >+ if (unp != NULL) { >+ tvp = unp->un_uppervp != NULL ? >+ unp->un_uppervp : unp->un_lowervp; >+ /* >+ * Hold the target vnode to prevent a concurrent unionfs >+ * unmount from causing it to be recycled once the interlock >+ * is dropped. >+ */ >+ vholdnz(tvp); >+ } >+ VI_UNLOCK(ap->a_vp); >+ if (tvp != NULL) { >+ VOP_UNP_DETACH(tvp); >+ vdrop(tvp); >+ } >+ return (0); >+} >+ > struct vop_vector unionfs_vnodeops = { > .vop_default = &default_vnodeops, > >@@ -2830,5 +2822,8 @@ struct vop_vector unionfs_vnodeops = { > .vop_vput_pair = unionfs_vput_pair, > .vop_set_text = unionfs_set_text, > .vop_unset_text = unionfs_unset_text, >+ .vop_unp_bind = unionfs_unp_bind, >+ .vop_unp_connect = unionfs_unp_connect, >+ .vop_unp_detach = unionfs_unp_detach, > }; > VFS_VOP_VECTOR_REGISTER(unionfs_vnodeops); >diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c >index 5d39e5ea91c1..dacb40e5ef99 100644 >--- a/sys/kern/uipc_usrreq.c >+++ b/sys/kern/uipc_usrreq.c >@@ -622,8 +622,19 @@ uipc_bindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td) > error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, > &vattr); > #endif >- if (error == 0) >+ if (error == 0) { >+ /* >+ * The prior lookup may have left LK_SHARED in cn_lkflags, >+ * and VOP_CREATE technically only requires the new vnode to >+ * be locked shared. Most filesystems will return the new vnode >+ * locked exclusive regardless, but we should explicitly >+ * specify that here since we require it and assert to that >+ * effect below. >+ */ >+ nd.ni_cnd.cn_lkflags = (nd.ni_cnd.cn_lkflags & ~LK_TYPE_MASK) | >+ LK_EXCLUSIVE; > error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); >+ } > NDFREE_PNBUF(&nd); > if (error) { > VOP_VPUT_PAIR(nd.ni_dvp, NULL, true);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 275871
:
247210
|
247211
|
248076
| 248162