All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pavel Emelyanov <xemul@parallels.com>
To: Hugh Dickins <hughd@google.com>, Nick Piggin <npiggin@kernel.dk>,
	Andrea Arcangeli <aarcange@redhat.com>,
	Rik van Riel <riel@redhat.com>,
	Dave Hansen <dave@linux.vnet.ibm.com>,
	Alexa
Cc: linux-fsdevel <linux-fsdevel@vger.kernel.org>
Subject: [PATCH 8/13] vfs: Introduce the dentry mobs
Date: Tue, 03 May 2011 16:18:33 +0400	[thread overview]
Message-ID: <4DBFF299.6090101@parallels.com> (raw)
In-Reply-To: <4DBFF1AD.90303@parallels.com>

The dentry mobs are the sets of dentries, that

* belong to one subtree growing from some dentry
* are limited in size per-mob
* have the unused dentries stored in the mob's LRU list

At this point all this patch does it moves the nr_dentry, the nr_dentry_max
and the dentry_lru on the static init_dentry_mob structure. The ability to
create more mobs will be introduced in the next patches.

Signed-off-by: Pavel Emelyanov <xemul@openvz.org>

---
 fs/dcache.c            |   46 ++++++++++++++++++++++++++--------------------
 include/linux/dcache.h |    7 +++++++
 2 files changed, 33 insertions(+), 20 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index c5179c3..bfe047d 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -123,14 +123,14 @@ struct dentry_stat_t dentry_stat = {
 	.age_limit = 45,
 };
 
-static struct percpu_counter nr_dentry __cacheline_aligned_in_smp;
-static unsigned long nr_dentry_max;
+static struct dentry_mob init_dentry_mob;
 
 #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
 int proc_nr_dentry(ctl_table *table, int write, void __user *buffer,
 		   size_t *lenp, loff_t *ppos)
 {
-	dentry_stat.nr_dentry = percpu_counter_sum_positive(&nr_dentry);
+	dentry_stat.nr_dentry =
+		percpu_counter_sum_positive(&init_dentry_mob.nr_dentry);
 	return proc_dointvec(table, write, buffer, lenp, ppos);
 }
 #endif
@@ -151,7 +151,7 @@ static void __d_free(struct rcu_head *head)
 static void d_free(struct dentry *dentry)
 {
 	BUG_ON(dentry->d_count);
-	percpu_counter_dec(&nr_dentry);
+	percpu_counter_dec(&dentry->d_mob->nr_dentry);
 	if (dentry->d_op && dentry->d_op->d_release)
 		dentry->d_op->d_release(dentry);
 
@@ -224,7 +224,6 @@ static void dentry_unlink_inode(struct dentry * dentry)
 		iput(inode);
 }
 
-static LIST_HEAD(dentry_lru);
 /*
  * dentry_lru_(add|del|move_tail) must be called with d_lock held.
  */
@@ -232,7 +231,7 @@ static void dentry_lru_add(struct dentry *dentry)
 {
 	if (list_empty(&dentry->d_lru)) {
 		spin_lock(&dcache_lru_lock);
-		list_add(&dentry->d_lru, &dentry_lru);
+		list_add(&dentry->d_lru, &dentry->d_mob->dentry_lru);
 		dentry_stat.nr_unused++;
 		spin_unlock(&dcache_lru_lock);
 	}
@@ -844,7 +843,7 @@ static int shrink_dentry_list(struct list_head *list)
  * This function may fail to free any resources if all the dentries are in use.
  */
 
-static int prune_dcache(int count)
+static int prune_dcache(struct dentry_mob *mob, int count)
 {
 	/* called from prune_dcache() and shrink_dcache_parent() */
 	struct dentry *dentry;
@@ -853,8 +852,8 @@ static int prune_dcache(int count)
 
 relock:
 	spin_lock(&dcache_lru_lock);
-	while (!list_empty(&dentry_lru)) {
-		dentry = list_entry(dentry_lru.prev, struct dentry, d_lru);
+	while (!list_empty(&mob->dentry_lru)) {
+		dentry = list_entry(mob->dentry_lru.prev, struct dentry, d_lru);
 
 		if (!spin_trylock(&dentry->d_lock)) {
 			spin_unlock(&dcache_lru_lock);
@@ -880,7 +879,7 @@ relock:
 		cond_resched_lock(&dcache_lru_lock);
 	}
 	if (!list_empty(&referenced))
-		list_splice(&referenced, &dentry_lru);
+		list_splice(&referenced, &mob->dentry_lru);
 	spin_unlock(&dcache_lru_lock);
 
 	return shrink_dentry_list(&tmp);
@@ -1060,7 +1059,7 @@ static int shrink_dcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask)
 	if (nr) {
 		if (!(gfp_mask & __GFP_FS))
 			return -1;
-		prune_dcache(nr);
+		prune_dcache(&init_dentry_mob, nr);
 	}
 
 	return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
@@ -1071,15 +1070,17 @@ static struct shrinker dcache_shrinker = {
 	.seeks = DEFAULT_SEEKS,
 };
 
-static int dcache_mem_check(void)
+static int dcache_mem_check(struct dentry_mob *dmob)
 {
-	if (percpu_counter_read_positive(&nr_dentry) <= nr_dentry_max)
+	if (percpu_counter_read_positive(&dmob->nr_dentry) <=
+			dmob->nr_dentry_max)
 		return 0;
 
 	do {
-		if (percpu_counter_sum_positive(&nr_dentry) <= nr_dentry_max)
+		if (percpu_counter_sum_positive(&dmob->nr_dentry) <=
+				dmob->nr_dentry_max)
 			return 0;
-	} while (prune_dcache(nr_dentry_max >> 6) > 0);
+	} while (prune_dcache(dmob, dmob->nr_dentry_max >> 6) > 0);
 
 	return -ENOMEM;
 }
@@ -1098,8 +1099,10 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
 {
 	struct dentry *dentry;
 	char *dname;
+	struct dentry_mob *dmob;
 
-	if (dcache_mem_check())
+	dmob = &init_dentry_mob;
+	if (dcache_mem_check(dmob))
 		return NULL;
 
 	dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);
@@ -1136,6 +1139,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
 	INIT_LIST_HEAD(&dentry->d_subdirs);
 	INIT_LIST_HEAD(&dentry->d_alias);
 	INIT_LIST_HEAD(&dentry->d_u.d_child);
+	dentry->d_mob = dmob;
 
 	if (parent) {
 		spin_lock(&parent->d_lock);
@@ -1151,7 +1155,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
 		spin_unlock(&parent->d_lock);
 	}
 
-	percpu_counter_inc(&nr_dentry);
+	percpu_counter_inc(&dmob->nr_dentry);
 
 	return dentry;
 }
@@ -2860,9 +2864,11 @@ static void __init dcache_init(void)
 {
 	int loop;
 
-	percpu_counter_init(&nr_dentry, 0);
-	nr_dentry_max = 80 * 1024 * 1024 / sizeof(struct dentry);
-	printk("nr_dentry_max = %lu\n", nr_dentry_max);
+	percpu_counter_init(&init_dentry_mob.nr_dentry, 0);
+	init_dentry_mob.nr_dentry_max = 80 * 1024 * 1024 / sizeof(struct dentry);
+	INIT_LIST_HEAD(&init_dentry_mob.dentry_lru);
+
+	printk("nr_dentry_max = %lu\n", init_dentry_mob.nr_dentry_max);
 
 	/* 
 	 * A constructor could be added for stable state like the lists,
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 64848dd..80bb9e4 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -48,6 +48,12 @@ struct dentry_stat_t {
 };
 extern struct dentry_stat_t dentry_stat;
 
+struct dentry_mob {
+	struct percpu_counter nr_dentry;
+	unsigned long nr_dentry_max;
+	struct list_head dentry_lru;
+};
+
 /*
  * Compare 2 name strings, return 0 if they match, otherwise non-zero.
  * The strings are both count bytes long, and count is non-zero.
@@ -143,6 +149,7 @@ struct dentry {
 	} d_u;
 	struct list_head d_subdirs;	/* our children */
 	struct list_head d_alias;	/* inode alias list */
+	struct dentry_mob *d_mob;
 };
 
 /*
-- 
1.5.5.6

  parent reply	other threads:[~2011-05-03 12:18 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-03 12:14 [RFC][PATCH 0/13] Per-container dcache management (and a bit more) Pavel Emelyanov
2011-05-03 12:15 ` [PATCH 1/13] vfs: Lighten r/o rename_lock lockers Pavel Emelyanov
2011-05-03 12:15 ` [PATCH 2/13] vfs: Factor out rename_lock locking Pavel Emelyanov
2011-05-03 12:16 ` [PATCH 3/13] vfs: Make the rename_lock per-sb Pavel Emelyanov
2011-05-03 12:16 ` [PATCH 4/13] vfs: Factor out tree (of four) shrinkers code Pavel Emelyanov
2011-05-03 12:17 ` [PATCH 5/13] vfs: Make dentry LRU list global Pavel Emelyanov
2011-05-03 12:17 ` [PATCH 6/13] vfs: Turn the nr_dentry into percpu_counter Pavel Emelyanov
2011-05-03 12:18 ` [PATCH 7/13] vfs: Limit the number of dentries globally Pavel Emelyanov
2011-05-03 12:18 ` Pavel Emelyanov [this message]
2011-06-18 13:40   ` [PATCH 8/13] vfs: Introduce the dentry mobs Andrea Arcangeli
2011-05-03 12:18 ` [PATCH 9/13] vfs: More than one mob management Pavel Emelyanov
2011-05-03 12:19 ` [PATCH 10/13] vfs: Routnes for setting mob size and getting stats Pavel Emelyanov
2011-05-03 12:19 ` [PATCH 11/13] vfs: Make shrink_dcache_memory prune dcache from all mobs Pavel Emelyanov
2011-05-03 12:20 ` [PATCH 12/13] vfs: Mobs creation and mgmt API Pavel Emelyanov
2011-05-03 12:20 ` [PATCH 13/13] vfs: Dentry mobs listing in proc Pavel Emelyanov
2011-05-06  1:05 ` [RFC][PATCH 0/13] Per-container dcache management (and a bit more) Dave Chinner
2011-05-06 12:15   ` Pavel Emelyanov
2011-05-07  0:01     ` Dave Chinner
2011-05-10 11:18       ` Pavel Emelyanov
2011-06-18 13:30       ` Andrea Arcangeli
2011-06-20  0:49         ` Dave Chinner
2011-07-04  5:32           ` Pavel Emelyanov
2011-05-23  6:43 ` Pavel Emelyanov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4DBFF299.6090101@parallels.com \
    --to=xemul@parallels.com \
    --cc=aarcange@redhat.com \
    --cc=dave@linux.vnet.ibm.com \
    --cc=hughd@google.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=npiggin@kernel.dk \
    --cc=riel@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.