[RFC] [PATCH] Fix warning at fs/dcache.c:430 dentry_free

Helge Deller <[email protected]>
Newsgroups org.kernel.vger.linux-parisc,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel
Message-ID <adQO8B0rkR2ftusI@p100>
The debian buildd servers for the parisc architecture crash reproduceably when
building the webkit2gtk debian package, shortly after having shown the warning
below.

This patch keeps the lock of the dentry up until when the dentry is given back
to the cache and after having freed the "external dentry name".

I'm not sure if this patch is really correct, but it seems to have fixed the
problem, although more testing is needed.

 kernel: WARNING: CPU: 2 PID: 65 at fs/dcache.c:430 dentry_free+0x15c/0x188
 kernel: Modules linked in: binfmt_misc ipmi_si ipmi_devintf ipmi_msghandler sg configfs nfnetlink autofs4 ex>
 kernel: CPU: 2 UID: 0 PID: 65 Comm: kswapd0 Tainted: G        W  6.18.15+deb14-parisc64 #1 NONE  De>
 kernel: Hardware name: 9000/800/rp4440
 kernel:
 kernel:  IAOQ[0]: dentry_free+0x15c/0x188
 kernel:  IAOQ[1]: dentry_free+0x160/0x188
 kernel:  RP(r2): __dentry_kill+0x2a4/0x338
 kernel: Backtrace:
 kernel:  [<00000000408d9eb0>] __dentry_kill+0x2a4/0x338
 kernel:  [<00000000408dc270>] shrink_dentry_list+0xfc/0x1d0
 kernel:  [<00000000408dcae4>] prune_dcache_sb+0x88/0xc0
 kernel:  [<00000000408a6410>] super_cache_scan+0x2bc/0x440
 kernel:  [<0000000040742f38>] do_shrink_slab+0x254/0x610
 kernel:  [<00000000407449b4>] shrink_slab+0x4d8/0x860
 kernel:  [<000000004073948c>] shrink_one+0x108/0x468
 kernel:  [<000000004073f270>] shrink_node+0xfdc/0x17a0
 kernel:  [<000000004074016c>] balance_pgdat+0x738/0xfb0
 kernel:  [<0000000040740da4>] kswapd+0x3c0/0x788
 kernel:  [<00000000403b35cc>] kthread+0x230/0x430
 kernel:  [<000000004031d020>] ret_from_kernel_thread+0x20/0x28

Signed-off-by: Helge Deller <[email protected]>


diff --git a/fs/dcache.c b/fs/dcache.c
index 7ba1801d8132..c1123787d3bd 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -343,6 +343,7 @@ static void __d_free(struct rcu_head *head)
 {
 	struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
 
+	spin_unlock(&dentry->d_lock);
 	kmem_cache_free(dentry_cache, dentry); 
 }
 
@@ -350,6 +351,7 @@ static void __d_free_external(struct rcu_head *head)
 {
 	struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
 	kfree(external_name(dentry));
+	spin_unlock(&dentry->d_lock);
 	kmem_cache_free(dentry_cache, dentry);
 }
 
@@ -684,9 +686,10 @@ static struct dentry *__dentry_kill(struct dentry *dentry)
 	dentry_unlist(dentry);
 	if (dentry->d_flags & DCACHE_SHRINK_LIST)
 		can_free = false;
-	spin_unlock(&dentry->d_lock);
 	if (likely(can_free))
 		dentry_free(dentry);
+	else
+		spin_unlock(&dentry->d_lock);
 	if (parent && --parent->d_lockref.count) {
 		spin_unlock(&parent->d_lock);
 		return NULL;
@@ -1165,9 +1168,10 @@ void shrink_dentry_list(struct list_head *list)
 			rcu_read_unlock();
 			d_shrink_del(dentry);
 			can_free = dentry->d_flags & DCACHE_DENTRY_KILLED;
-			spin_unlock(&dentry->d_lock);
 			if (can_free)
 				dentry_free(dentry);
+			else
+				spin_unlock(&dentry->d_lock);
 			continue;
 		}
 		d_shrink_del(dentry);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.