git: 6e1eabadcb1d - main - ffs_syncvnode(): avoid a LoR for SU

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sat, 14 Jan 2023 18:37:22 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=6e1eabadcb1d554ab6c0ad8ce1d82f6748cc80b4

commit 6e1eabadcb1d554ab6c0ad8ce1d82f6748cc80b4
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2023-01-07 12:22:18 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-01-14 18:28:11 +0000

    ffs_syncvnode(): avoid a LoR for SU
    
    There is another case where SU code does ffs_syncvnode(dvp) for the
    parent directory dvp while the child vnode vp is locked.  Avoid the
    issue by relocking and returning ERELOOKUP to indicate the need of
    resync.
    
    Reported by:    jkim
    Reviewed by:    mckusick
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D37997
---
 sys/ufs/ffs/ffs_softdep.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 7c9473737e68..ef1753862595 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -12758,9 +12758,15 @@ restart:
 					pagedep_new_block = pagedep->pd_state & NEWBLOCK;
 					FREE_LOCK(ump);
 					locked = 0;
-					if (pagedep_new_block && (error =
-					    ffs_syncvnode(pvp, MNT_WAIT, 0))) {
+					if (pagedep_new_block) {
+						VOP_UNLOCK(vp);
+						error = ffs_syncvnode(pvp,
+						    MNT_WAIT, 0);
+						if (error == 0)
+							error = ERELOOKUP;
 						vput(pvp);
+						vn_lock(vp, LK_EXCLUSIVE |
+						    LK_RETRY);
 						return (error);
 					}
 				}