Index: sys/fs/unionfs/union.h =================================================================== --- sys/fs/unionfs/union.h +++ sys/fs/unionfs/union.h @@ -137,15 +137,15 @@ struct componentname *, struct componentname *, struct thread *, char *, int, u_long); int unionfs_relookup_for_create(struct vnode *, struct componentname *, - struct thread *td); + struct thread *); int unionfs_relookup_for_delete(struct vnode *, struct componentname *, struct thread *); int unionfs_relookup_for_rename(struct vnode *, struct componentname *, - struct thread *td); + struct thread *); #ifdef DIAGNOSTIC -struct vnode *unionfs_checklowervp(struct vnode *vp, char *fil, int lno); -struct vnode *unionfs_checkuppervp(struct vnode *vp, char *fil, int lno); +struct vnode *unionfs_checklowervp(struct vnode *, char *, int); +struct vnode *unionfs_checkuppervp(struct vnode *, char *, int); #define UNIONFSVPTOLOWERVP(vp) unionfs_checklowervp((vp), __FILE__, __LINE__) #define UNIONFSVPTOUPPERVP(vp) unionfs_checkuppervp((vp), __FILE__, __LINE__) #else Index: sys/fs/unionfs/union_subr.c =================================================================== --- sys/fs/unionfs/union_subr.c +++ sys/fs/unionfs/union_subr.c @@ -153,8 +153,8 @@ hd = unionfs_get_hashhead(dvp, lookup); LIST_FOREACH(unp, hd, un_hash) { - if ((unp->un_uppervp == lookup) || - (unp->un_lowervp == lookup)) { + if (unp->un_uppervp == lookup || + unp->un_lowervp == lookup) { vp = UNIONFSTOV(unp); VI_LOCK_FLAGS(vp, MTX_DUPOK); vp->v_iflag &= ~VI_OWEINACT; @@ -183,10 +183,10 @@ { struct vnode *vp; - KASSERT((uvp == NULLVP || uvp->v_type == VDIR), - ("unionfs_get_cached_vnode: v_type != VDIR")); - KASSERT((lvp == NULLVP || lvp->v_type == VDIR), - ("unionfs_get_cached_vnode: v_type != VDIR")); + KASSERT(uvp == NULLVP || uvp->v_type == VDIR, + ("%s: v_type != VDIR", __func__)); + KASSERT(lvp == NULLVP || lvp->v_type == VDIR, + ("%s: v_type != VDIR", __func__)); vp = NULLVP; VI_LOCK(dvp); @@ -209,10 +209,10 @@ struct unionfs_node_hashhead *hd; struct vnode *vp; - KASSERT((uncp->un_uppervp==NULLVP || uncp->un_uppervp->v_type==VDIR), - ("unionfs_ins_cached_vnode: v_type != VDIR")); - KASSERT((uncp->un_lowervp==NULLVP || uncp->un_lowervp->v_type==VDIR), - ("unionfs_ins_cached_vnode: v_type != VDIR")); + KASSERT(uncp->un_uppervp==NULLVP || uncp->un_uppervp->v_type==VDIR, + ("%s: v_type != VDIR", __func__)); + KASSERT(uncp->un_lowervp==NULLVP || uncp->un_lowervp->v_type==VDIR, + ("%s: v_type != VDIR", __func__)); vp = NULLVP; VI_LOCK(dvp); @@ -236,9 +236,9 @@ static void unionfs_rem_cached_vnode(struct unionfs_node *unp, struct vnode *dvp) { - KASSERT((unp != NULL), ("unionfs_rem_cached_vnode: null node")); - KASSERT((dvp != NULLVP), - ("unionfs_rem_cached_vnode: null parent vnode")); + KASSERT(unp != NULL, ("%s: null node", __func__)); + KASSERT(dvp != NULLVP, + ("%s: null parent vnode", __func__)); VI_LOCK(dvp); if (unp->un_hash.le_prev != NULL) { @@ -320,7 +320,7 @@ *vpp = NULLVP; if (uppervp == NULLVP && lowervp == NULLVP) - panic("unionfs_nodeget: upper and lower is null"); + panic("%s: upper and lower is null", __func__); vt = (uppervp != NULLVP ? uppervp->v_type : lowervp->v_type); @@ -439,6 +439,9 @@ struct vnode *dvp; int count; + if (lockmgr(&(vp->v_lock), LK_EXCLUSIVE, NULL) != 0) + panic("%s: failed to acquire lock for vnode lock", __func__); + /* * Use the interlock to protect the clearing of v_data to * prevent faults in unionfs_lock(). @@ -459,6 +462,16 @@ VOP_ADD_WRITECOUNT(lvp, -vp->v_writecount); } else if (vp->v_writecount < 0) vp->v_writecount = 0; + if (unp->un_hashtbl != NULL) { + for (count = 0; count <= UNIONFSHASHMASK; count++) { + hd = unp->un_hashtbl + count; + LIST_FOREACH_SAFE(unp_t1, hd, un_hash, unp_t2) { + LIST_REMOVE(unp_t1, un_hash); + unp_t1->un_hash.le_next = NULL; + unp_t1->un_hash.le_prev = NULL; + } + } + } VI_UNLOCK(vp); if (lvp != NULLVP) @@ -469,9 +482,6 @@ if (dvp != NULLVP) unionfs_rem_cached_vnode(unp, dvp); - if (lockmgr(vp->v_vnlock, LK_EXCLUSIVE, VI_MTX(vp)) != 0) - panic("the lock for deletion is unacquirable."); - if (lvp != NULLVP) vrele(lvp); if (uvp != NULLVP) @@ -483,14 +493,6 @@ } if (unp->un_hashtbl != NULL) { - for (count = 0; count <= UNIONFSHASHMASK; count++) { - hd = unp->un_hashtbl + count; - LIST_FOREACH_SAFE(unp_t1, hd, un_hash, unp_t2) { - LIST_REMOVE(unp_t1, un_hash); - unp_t1->un_hash.le_next = NULL; - unp_t1->un_hash.le_prev = NULL; - } - } hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, UNIONFSHASHMASK); } @@ -521,8 +523,8 @@ pid = td->td_proc->p_pid; - KASSERT(NULL != unspp, ("null pointer")); - ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), "unionfs_get_node_status"); + KASSERT(NULL != unspp, ("%s: NULL status", __func__)); + ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), __func__); LIST_FOREACH(unsp, &(unp->un_unshead), uns_list) { if (unsp->uns_pid == pid) { @@ -549,8 +551,8 @@ unionfs_tryrem_node_status(struct unionfs_node *unp, struct unionfs_node_status *unsp) { - KASSERT(NULL != unsp, ("null pointer")); - ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), "unionfs_get_node_status"); + KASSERT(NULL != unsp, ("%s: NULL status", __func__)); + ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), __func__); if (0 < unsp->uns_lower_opencnt || 0 < unsp->uns_upper_opencnt) return; @@ -794,19 +796,20 @@ vp = UNIONFSTOV(unp); lvp = unp->un_lowervp; - ASSERT_VOP_ELOCKED(lvp, "unionfs_node_update"); + ASSERT_VOP_ELOCKED(lvp, __func__); dvp = unp->un_dvp; /* - * lock update + * Uppdate the upper vnode's lock state to match the lower vnode, + * and then switch the unionfs vnode's lock to the upper vnode. */ + lockrec = lvp->v_vnlock->lk_recurse; + for (count = 0; count < lockrec; count++) + vn_lock(uvp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY); VI_LOCK(vp); unp->un_uppervp = uvp; vp->v_vnlock = uvp->v_vnlock; VI_UNLOCK(vp); - lockrec = lvp->v_vnlock->lk_recurse; - for (count = 0; count < lockrec; count++) - vn_lock(uvp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY); /* * Re-cache the unionfs vnode against the upper vnode @@ -982,7 +985,7 @@ unionfs_create_uppervattr_core(ump, &lva, uvap, td); if (unp->un_path == NULL) - panic("unionfs: un_path is null"); + panic("%s: NULL un_path", __func__); nd.ni_cnd.cn_namelen = unp->un_pathlen; nd.ni_cnd.cn_pnbuf = unp->un_path; @@ -1202,7 +1205,7 @@ */ char buf[256 * 6]; - ASSERT_VOP_ELOCKED(vp, "unionfs_check_rmdir"); + ASSERT_VOP_ELOCKED(vp, __func__); eofflag = 0; uvp = UNIONFSVPTOUPPERVP(vp); @@ -1244,7 +1247,8 @@ break; if (eofflag == 0 && uio.uio_resid == sizeof(buf)) { #ifdef DIAGNOSTIC - panic("bad readdir response from lower FS."); + panic("%s: bad readdir response from lower FS", + __func__); #endif break; } @@ -1316,12 +1320,12 @@ #ifdef notyet if (vp->v_op != unionfs_vnodeop_p) { - printf("unionfs_checkuppervp: on non-unionfs-node.\n"); + printf("%s: on non-unionfs-node.\n", __func__); #ifdef KDB kdb_enter(KDB_WHY_UNIONFS, "unionfs_checkuppervp: on non-unionfs-node.\n"); #endif - panic("unionfs_checkuppervp"); + panic("%s", __func__); } #endif return (unp->un_uppervp); @@ -1336,12 +1340,12 @@ #ifdef notyet if (vp->v_op != unionfs_vnodeop_p) { - printf("unionfs_checklowervp: on non-unionfs-node.\n"); + printf("%s: on non-unionfs-node.\n", __func__); #ifdef KDB kdb_enter(KDB_WHY_UNIONFS, "unionfs_checklowervp: on non-unionfs-node.\n"); #endif - panic("unionfs_checklowervp"); + panic("%s", __func__); } #endif return (unp->un_lowervp);