Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1036

kernel-2.6.18-238.el5.src.rpm

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++;
 		}