try_lookup unlocks the directory before fshelp_fetch_root, which locks
only the translated node again.  Every outcome but ENOENT then goes to
OUT, which unlocks the directory a second time with diskfs_nput.  A
thread holding the directory, such as another lookup in it, loses its
lock, as with any lookup through a translator, e.g. under /dev or
/servers.

Release only the directory's reference on those exits.
---
 libdiskfs/dir-lookup.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/libdiskfs/dir-lookup.c b/libdiskfs/dir-lookup.c
index fd444be21..eef922eaf 100644
--- a/libdiskfs/dir-lookup.c
+++ b/libdiskfs/dir-lookup.c
@@ -277,6 +277,12 @@ diskfs_S_dir_lookup (struct protid *dircred,
 
          if (err != ENOENT)
            {
+             /* DNP is still unlocked: only its reference goes.  */
+             if (np != dnp)
+               {
+                 diskfs_nrele (dnp);
+                 dnp = 0;
+               }
              *retry_port_type = MACH_MSG_TYPE_MOVE_SEND;
              if (!err)
                {
-- 
2.56.0


Reply via email to