Re: 6.19 tmpfs __d_lookup() lockup

From: Hugh Dickins

Date: Fri Dec 12 2025 - 05:12:37 EST


On Thu, 11 Dec 2025, Hugh Dickins wrote:
> On Fri, 12 Dec 2025, Al Viro wrote:
> >
> > A few more things to check:
> >
> > 1) do we, by any chance, ever see dentry_free() called with
> > dentry->d_flags & DCACHE_PERSISTENT?
>
> No.
>
> >
> > 2) does d_make_persistent() ever call __d_rehash() when called with
> > dentry->d_sb->s_magic == TMPFS_MAGIC?
>
> Yes, both if shmem_whiteout() does its d_rehash() and if it does not.
>
> >
> > 3) is shmem_whiteout() ever called? If that's the case, could you try
> > to remove that d_rehash() call in it and see what happens? Because
> > that's another place where shmem is playing odd games...
>
> Yes, shmem_whiteout() does get called.
>
> And when I remove that d_rehash() call from it, 269 476 650 and 750
> complete without locking up. And when I remove the WARN_ON()s
> inserted for 2) and 3), then they pass.
>
> You are very much on the right lines!

Well, more than that: it's exactly the right thing to do, isn't it?
shmem_mknod() already called d_make_peristent() which called __d_rehash(),
calling it a second time naturally leads to the __d_lookup() lockup seen.
And I can't see a place now for shmem_whiteout()'s "Cheat and hash" comment.

Al, may I please leave you to send in the fix to Christian and/or Linus?
You may have noticed other things on the way, that you might want to add.

But if your patch resembles the below (which has now passed xfstests
auto runs on tmpfs), please feel free to add or omit any or all of

Reported-by: Hugh Dickins <hughd@xxxxxxxxxx>
Acked-by: Hugh Dickins <hughd@xxxxxxxxxx>
Tested-by: Hugh Dickins <hughd@xxxxxxxxxx>

Thanks a lot for your very quick resolution!
Hugh

--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -4023,18 +4023,7 @@ static int shmem_whiteout(struct mnt_idmap *idmap,
error = shmem_mknod(idmap, old_dir, whiteout,
S_IFCHR | WHITEOUT_MODE, WHITEOUT_DEV);
dput(whiteout);
- if (error)
- return error;
-
- /*
- * Cheat and hash the whiteout while the old dentry is still in
- * place, instead of playing games with FS_RENAME_DOES_D_MOVE.
- *
- * d_lookup() will consistently find one of them at this point,
- * not sure which one, but that isn't even important.
- */
- d_rehash(whiteout);
- return 0;
+ return error;
}

/*