From: Josef Bacik <josef@redhat.com> Date: Mon, 23 Aug 2010 13:57:14 -0400 Subject: [fs] fix dcache accounting bug Message-id: <20100823135714.GG2404@localhost.localdomain> Patchwork-id: 27773 O-Subject: [RHEL 5.6][PATCH] fix dcache accounting bug Bugzilla: 596548 RH-Acked-by: Jeff Layton <jlayton@redhat.com> RH-Acked-by: Rik van Riel <riel@redhat.com> RH-Acked-by: Jerome Marchand <jmarchan@redhat.com> Hello, This is related to bz 596548 and has been verified by the customer to fix their problem. The problem is everywhere we do this if (!list_empty(&dentry->d_lru) { nr_unused--; list_del(&dentry->d_lru); } and we do the same thing when we move dentries from the dentry_unused list to our private dispose list. The problem with this is we don't do nr_unused++, so if somebody else comes in and references the dentry while it's on the dispose list, the above code will run and nr_unused will have been decremented twice for the same dentry. To fix this we make it that when we add the dentry to the dispose list we do a nr_unused++, and then unconditionally do an nr_unused-- in prune_dcache since we always will be removing an unused dentry from a list. Thanks, Josef Signed-off-by: Jarod Wilson <jarod@redhat.com> diff --git a/fs/dcache.c b/fs/dcache.c index ebc4b5e..86eb964 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -419,9 +419,9 @@ static void prune_dcache(int count, struct super_block *sb, tmp = dentry_unused.prev; if (tmp == &dentry_unused) break; - dentry_stat.nr_unused--; } + dentry_stat.nr_unused--; prefetch(tmp->prev); list_del_init(tmp); dentry = list_entry(tmp, struct dentry, d_lru); @@ -769,6 +769,7 @@ resume: * of the unused list for prune_dcache */ if (!atomic_read(&dentry->d_count)) { + dentry_stat.nr_unused++; list_add_tail(&dentry->d_lru, dispose_list); found++; }