* Al Viro <viro@xxxxxxxxxxxxxxxxxx>: > On Wed, Jul 20, 2022 at 08:53:53AM +0200, Helge Deller wrote: > > On 7/20/22 05:29, Al Viro wrote: > > > On Sat, Jul 16, 2022 at 07:27:30AM +0200, Helge Deller wrote: > > >> On 7/15/22 15:33, Hillf Danton wrote: > > > > > >> [108565.341434] dentry->d_u.d_rcu = 0x416be770 > > > > > > Incidentally, does that match the address of __d_free() on your build, > > > or is it something different? > > > > I don't think it's __d_free(). > > The source is: > > pr_err("dentry->d_u.d_rcu = %pS\n", dentry->d_u.d_rcu.func); > > so the "%pS" would probably have resolved the pointer to string "__d_free" (or something else). > > ???? > > That should've taken a word from desc->addr and printed it. > If it had managed to get to a string (you'd needed to have > CONFIG_KALLSYMS enabled), it would've printed it as a string, > not as hex address. Seriously, check System.map for that > kernel... CONFIG_KALLSYMS is enabled - otherwise I wouldn't see the backtrace either (just to be sure I did check the .config again). But it might be, that when I produced that debug info I had %p instead of %pS - that might explain why the function name wasn't resolved. The kernel functions on my build on parisc range from 0000000040100000 T __init_begin to 0000000041700000 D _end In my current System.map (which may not fit the address above!) I see: 00000000416bda50 d in_lookup_hashtable 00000000416bfa50 d counter.0 so, 0x416be770 would be in in_lookup_hashtable(). Does that make sense? Again - this is a somewhat newer build... Btw, you asked if there were any other private discussions/mails on other mailing lists: There are none, only those which are in this mail thread. Below is the current patch with which I will try to reproduce the issue. I'll disable hashed pointers too. Any other info/patches I should add? Reproducing it is time-consuming. It takes me usually a day to trigger. Helge diff --git a/fs/dcache.c b/fs/dcache.c index 93f4f5ee07bf..047729fc1a97 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -360,11 +360,32 @@ static inline void __d_clear_type_and_inode(struct dentry *dentry) this_cpu_inc(nr_dentry_negative); } +static void show_dentry_info(struct dentry *dentry) +{ + pr_err("dentry = %px\n", dentry); + pr_err("spin_is_locked(&dentry->d_lock) = %d\n", spin_is_locked(&dentry->d_lock)); + pr_err("dname_external(dentry) = %d\n", dname_external(dentry)); + pr_err("dentry->d_flags = 0x%x\n", dentry->d_flags); + // pr_err("ERROR on file %pd\n", &dentry); HANGS + pr_err("dentry->d_name.len = %d\n", dentry->d_name.len); + pr_err("dentry->d_name.hash = 0x%x\n", dentry->d_name.hash); + pr_err("dentry->d_lockref.count = %d\n", dentry->d_lockref.count); + pr_err("dentry->d_flags = 0x%x\n", dentry->d_flags); + pr_err("dentry->d_inode = %px\n", dentry->d_inode); + pr_err("dentry->d_parent = %px\n", dentry->d_parent); + pr_err("dentry->d_u.d_rcu = %pS\n", dentry->d_u.d_rcu.func); +} + static void dentry_free(struct dentry *dentry) { - WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias)); + int unhashed = hlist_unhashed(&dentry->d_u.d_alias); + if (WARN_ON(!unhashed)) { + show_dentry_info(dentry); + } if (unlikely(dname_external(dentry))) { struct external_name *p = external_name(dentry); + if (!unhashed) + pr_err("value of &p->u.count = %d\n", p->u.count.counter); if (likely(atomic_dec_and_test(&p->u.count))) { call_rcu(&dentry->d_u.d_rcu, __d_free_external); return; @@ -605,8 +626,13 @@ static void __dentry_kill(struct dentry *dentry) spin_unlock(&parent->d_lock); if (dentry->d_inode) dentry_unlink_inode(dentry); - else + else { + if (WARN_ON_ONCE(d_in_lookup(dentry))) { + show_dentry_info(dentry); + __d_lookup_done(dentry); + } spin_unlock(&dentry->d_lock); + } this_cpu_dec(nr_dentry); if (dentry->d_op && dentry->d_op->d_release) dentry->d_op->d_release(dentry); @@ -616,6 +642,8 @@ static void __dentry_kill(struct dentry *dentry) dentry->d_flags |= DCACHE_MAY_FREE; can_free = false; } + if (WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias))) + show_dentry_info(dentry); spin_unlock(&dentry->d_lock); if (likely(can_free)) dentry_free(dentry);