diff --git a/sys/sys/seqc.h b/sys/sys/seqc.h --- a/sys/sys/seqc.h +++ b/sys/sys/seqc.h @@ -45,13 +45,15 @@ #include +#define SEQC_MOD 1 + /* * Predicts from inline functions are not honored by clang. */ #define seqc_in_modify(seqc) ({ \ seqc_t __seqc = (seqc); \ \ - __predict_false(__seqc & 1); \ + __predict_false(__seqc & SEQC_MOD); \ }) static __inline void @@ -60,7 +62,7 @@ critical_enter(); MPASS(!seqc_in_modify(*seqcp)); - *seqcp += 1; + *seqcp += SEQC_MOD; atomic_thread_fence_rel(); } @@ -69,7 +71,7 @@ { atomic_thread_fence_rel(); - *seqcp += 1; + *seqcp += SEQC_MOD; MPASS(!seqc_in_modify(*seqcp)); critical_exit(); } @@ -85,7 +87,7 @@ seqc_read_notmodify(const seqc_t *seqcp) { - return (atomic_load_acq_int(__DECONST(seqc_t *, seqcp)) & ~1); + return (atomic_load_acq_int(__DECONST(seqc_t *, seqcp)) & ~SEQC_MOD); } static __inline seqc_t @@ -126,7 +128,7 @@ { MPASS(!seqc_in_modify(*seqcp)); - *seqcp += 1; + *seqcp += SEQC_MOD; atomic_thread_fence_rel(); } @@ -135,7 +137,7 @@ { atomic_thread_fence_rel(); - *seqcp += 1; + *seqcp += SEQC_MOD; MPASS(!seqc_in_modify(*seqcp)); } diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -3415,10 +3415,9 @@ if (vp != NULL) VOP_UNLOCK(vp); ffs_syncvnode(dvp, MNT_WAIT, 0); - VOP_UNLOCK(dvp); - /* Process vp before dvp as it may create .. removes. */ if (vp != NULL) { + VOP_UNLOCK(dvp); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (vp->v_data == NULL) { vn_lock_pair(dvp, false, vp, true); @@ -3429,12 +3428,11 @@ process_truncates(vp); FREE_LOCK(ump); VOP_UNLOCK(vp); - } - - vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); - if (dvp->v_data == NULL) { - vn_lock_pair(dvp, true, vp, false); - return (ERELOOKUP); + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); + if (dvp->v_data == NULL) { + vn_lock_pair(dvp, true, vp, false); + return (ERELOOKUP); + } } ACQUIRE_LOCK(ump); diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -1246,6 +1246,7 @@ int error = 0; struct mount *mp; ino_t ino; + seqc_t fdvp_s, fvp_s, tdvp_s, tvp_s; bool want_seqc_end; want_seqc_end = false; @@ -1269,6 +1270,8 @@ mp = NULL; goto releout; } + + fdvp_s = fvp_s = tdvp_s = tvp_s = SEQC_MOD; relock: /* * We need to acquire 2 to 4 locks depending on whether tvp is NULL @@ -1362,10 +1365,20 @@ } } - if (DOINGSOFTDEP(fdvp)) { + if (DOINGSUJ(fdvp) && + (seqc_in_modify(fdvp_s) || !vn_seqc_consistent(fdvp, fdvp_s) || + seqc_in_modify(fvp_s) || !vn_seqc_consistent(fvp, fvp_s) || + seqc_in_modify(tdvp_s) || !vn_seqc_consistent(tdvp, tdvp_s) || + (tvp != NULL && (seqc_in_modify(tvp_s) || + !vn_seqc_consistent(tvp, tvp_s))))) { error = softdep_prerename(fdvp, fvp, tdvp, tvp); if (error != 0) { if (error == ERELOOKUP) { + fdvp_s = vn_seqc_read_any(fdvp); + fvp_s = vn_seqc_read_any(fvp); + tdvp_s = vn_seqc_read_any(tdvp); + if (tvp != NULL) + tvp_s = vn_seqc_read_any(tvp); atomic_add_int(&rename_restarts, 1); goto relock; }