Skip to contentSkip to conversation

memcg: fix memcg_cache_name() to use cgroup_name()

PATCH In review Li Zefan 3 participants 25 messages Mar 21, 2013 – Mar 27, 2013

Subsystems (3)
lore
Share & tools
lore

Li Zefan

author
#0 lore raw

PATCH 1/1 memcg: fix memcg_cache_name() to use cgroup_name()

As cgroup supports rename, it's unsafe to dereference dentry->d_name without proper vfs locks. Fix this by using cgroup_name().

---

This patch depends on "cgroup: fix cgroup_path() vs rename() race", which has been queued for 3.10.

---
 mm/memcontrol.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)
mm/memcontrol.c +7 -8
index 53b8201..72be5c9 100644
@@ -3217,17 +3217,16 @@ void mem_cgroup_destroy_cache(struct kmem_cache *cachep)
 static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s)
 {
 	char *name;
-	struct dentry *dentry;
+
+	name = (char *)__get_free_page(GFP_TEMPORARY);
+	if (!name)
+		return NULL;
 
 	rcu_read_lock();
-	dentry = rcu_dereference(memcg->css.cgroup->dentry);
+	snprintf(name, PAGE_SIZE, "%s(%d:%s)", s->name, memcg_cache_id(memcg),
+		 cgroup_name(memcg->css.cgroup));
 	rcu_read_unlock();
 
-	BUG_ON(dentry == NULL);
-
-	name = kasprintf(GFP_KERNEL, "%s(%d:%s)", s->name,
-			 memcg_cache_id(memcg), dentry->d_name.name);
-
 	return name;
 }
 
@@ -3247,7 +3246,7 @@ static struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg,
 	if (new)
 		new->allocflags |= __GFP_KMEMCG;
 
-	kfree(name);
+	free_page((unsigned long)name);
 	return new;
 }
 
Signature · 7 lines
1.8.0.2

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#1 lore raw
Quoted 18 lines · Li Zefan

As cgroup supports rename, it's unsafe to dereference dentry->d_name without proper vfs locks. Fix this by using cgroup_name().

---

This patch depends on "cgroup: fix cgroup_path() vs rename() race", which has been queued for 3.10.

---
 mm/memcontrol.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)
mm/memcontrol.c +0 -0
index 53b8201..72be5c9 100644

mm/memcontrol.c void mem_cgroup_destroy_cache(struct kmem_cache *cachep) · line 3221

Quoted 6 lines
mm/memcontrol.c +2 -1
@@ -3217,17 +3217,16 @@ void mem_cgroup_destroy_cache(struct kmem_cache *cachep)
 static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s)
 {
 	char *name;
-	struct dentry *dentry;
+
+	name = (char *)__get_free_page(GFP_TEMPORARY);

Ouch. Can we use a static temporary buffer instead? This is called from workqueue context so we do not have to be afraid of the deep call chain. It is also not a hot path AFAICS.

Even GFP_ATOMIC for kasprintf would be an improvement IMO.

Quoted 33 lines
mm/memcontrol.c +5 -7
+	if (!name)
+		return NULL;
 
 	rcu_read_lock();
-	dentry = rcu_dereference(memcg->css.cgroup->dentry);
+	snprintf(name, PAGE_SIZE, "%s(%d:%s)", s->name, memcg_cache_id(memcg),
+		 cgroup_name(memcg->css.cgroup));
 	rcu_read_unlock();
 
-	BUG_ON(dentry == NULL);
-
-	name = kasprintf(GFP_KERNEL, "%s(%d:%s)", s->name,
-			 memcg_cache_id(memcg), dentry->d_name.name);
-
 	return name;
 }
 
@@ -3247,7 +3246,7 @@ static struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg,
 	if (new)
 		new->allocflags |= __GFP_KMEMCG;
 
-	kfree(name);
+	free_page((unsigned long)name);
 	return new;
 }
 
Signature · 6 lines
1.8.0.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
Signature · 8 lines
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#2 lore raw
Quoted 28 lines · Michal Hocko
Quoted 18 lines · Li Zefan

As cgroup supports rename, it's unsafe to dereference dentry->d_name without proper vfs locks. Fix this by using cgroup_name().

---

This patch depends on "cgroup: fix cgroup_path() vs rename() race", which has been queued for 3.10.

---
 mm/memcontrol.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)
mm/memcontrol.c +0 -0
index 53b8201..72be5c9 100644

mm/memcontrol.c void mem_cgroup_destroy_cache(struct kmem_cache *cachep) · line 3221

Quoted 6 lines
mm/memcontrol.c +2 -1
@@ -3217,17 +3217,16 @@ void mem_cgroup_destroy_cache(struct kmem_cache *cachep)
 static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s)
 {
 	char *name;
-	struct dentry *dentry;
+
+	name = (char *)__get_free_page(GFP_TEMPORARY);

Ouch. Can we use a static temporary buffer instead?

Quoted 2 lines

This is called from workqueue context so we do not have to be afraid of the deep call chain.

Bahh, I was thinking about two things at the same time and that is how it ends... I meant a temporary buffer on the stack. But a separate allocation sounds even easier.

Quoted 3 lines

It is also not a hot path AFAICS.

Even GFP_ATOMIC for kasprintf would be an improvement IMO.

What about the following (not even compile tested because I do not have cgroup_name in my tree yet):
---

mm/memcontrol.c +10 -5
index f608546..ede0382 100644
@@ -3370,13 +3370,18 @@ static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s)
 	struct dentry *dentry;
 
 	rcu_read_lock();
-	dentry = rcu_dereference(memcg->css.cgroup->dentry);
+	name = kasprintf(GFP_ATOMIC, "%s(%d:%s)", s->name,
+			 memcg_cache_id(memcg), cgroup_name(memcg->css.cgroup));
 	rcu_read_unlock();
 
-	BUG_ON(dentry == NULL);
-
-	name = kasprintf(GFP_KERNEL, "%s(%d:%s)", s->name,
-			 memcg_cache_id(memcg), dentry->d_name.name);
+	if (!name) {
+		name = kmalloc(PAGE_SIZE, GFP_KERNEL);
+		rcu_read_lock();
+		name = snprintf(name, PAGE_SIZE, "%s(%d:%s)", s->name,
+				memcg_cache_id(memcg),
+				cgroup_name(memcg->css.cgroup));
+		rcu_read_unlock();
+	}
 
 	return name;
 }
Signature · 2 lines
Michal Hocko
SUSE Labs
author
#3 lore raw
Quoted 29 lines · Michal Hocko
Quoted 27 lines · Michal Hocko
Quoted 18 lines · Li Zefan

As cgroup supports rename, it's unsafe to dereference dentry->d_name without proper vfs locks. Fix this by using cgroup_name().

---

This patch depends on "cgroup: fix cgroup_path() vs rename() race", which has been queued for 3.10.

---
 mm/memcontrol.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)
mm/memcontrol.c +0 -0
index 53b8201..72be5c9 100644

mm/memcontrol.c void mem_cgroup_destroy_cache(struct kmem_cache *cachep) · line 3221

Quoted 6 lines
mm/memcontrol.c +2 -1
@@ -3217,17 +3217,16 @@ void mem_cgroup_destroy_cache(struct kmem_cache *cachep)
 static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s)
 {
 	char *name;
-	struct dentry *dentry;
+
+	name = (char *)__get_free_page(GFP_TEMPORARY);

Ouch. Can we use a static temporary buffer instead?

Quoted 7 lines
Quoted 2 lines

This is called from workqueue context so we do not have to be afraid of the deep call chain.

Bahh, I was thinking about two things at the same time and that is how it ends... I meant a temporary buffer on the stack. But a separate allocation sounds even easier.

Actually I don't care much about which way to take. Use on-stack buffer (if stack usage is not a concern) or local static buffer (caller already held memcg_cache_mutex) is simplest.

But why it's bad to allocate a page for temp use?

Quoted 6 lines
Quoted 3 lines

It is also not a hot path AFAICS.

Even GFP_ATOMIC for kasprintf would be an improvement IMO.

What about the following (not even compile tested because I do not have cgroup_name in my tree yet):

No, it won't compile. ;)

Quoted 20 lines

---

mm/memcontrol.c +3 -5
index f608546..ede0382 100644
@@ -3370,13 +3370,18 @@ static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s)
 	struct dentry *dentry;
 
 	rcu_read_lock();
-	dentry = rcu_dereference(memcg->css.cgroup->dentry);
+	name = kasprintf(GFP_ATOMIC, "%s(%d:%s)", s->name,
+			 memcg_cache_id(memcg), cgroup_name(memcg->css.cgroup));
 	rcu_read_unlock();
 
-	BUG_ON(dentry == NULL);
-
-	name = kasprintf(GFP_KERNEL, "%s(%d:%s)", s->name,
-			 memcg_cache_id(memcg), dentry->d_name.name);
+	if (!name) {

mm/memcontrol.c static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s) · line 3387

Quoted 10 lines
mm/memcontrol.c +7 -0
+		name = kmalloc(PAGE_SIZE, GFP_KERNEL);
+		rcu_read_lock();
+		name = snprintf(name, PAGE_SIZE, "%s(%d:%s)", s->name,
+				memcg_cache_id(memcg),
+				cgroup_name(memcg->css.cgroup));
+		rcu_read_unlock();
+	}
 
 	return name;
 }

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#4 lore raw
Quoted 38 lines · Li Zefan
Quoted 29 lines · Michal Hocko
Quoted 27 lines · Michal Hocko
Quoted 18 lines · Li Zefan

As cgroup supports rename, it's unsafe to dereference dentry->d_name without proper vfs locks. Fix this by using cgroup_name().

---

This patch depends on "cgroup: fix cgroup_path() vs rename() race", which has been queued for 3.10.

---
 mm/memcontrol.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)
mm/memcontrol.c +0 -0
index 53b8201..72be5c9 100644

mm/memcontrol.c void mem_cgroup_destroy_cache(struct kmem_cache *cachep) · line 3221

Quoted 6 lines
mm/memcontrol.c +2 -1
@@ -3217,17 +3217,16 @@ void mem_cgroup_destroy_cache(struct kmem_cache *cachep)
 static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s)
 {
 	char *name;
-	struct dentry *dentry;
+
+	name = (char *)__get_free_page(GFP_TEMPORARY);

Ouch. Can we use a static temporary buffer instead?

Quoted 7 lines
Quoted 2 lines

This is called from workqueue context so we do not have to be afraid of the deep call chain.

Bahh, I was thinking about two things at the same time and that is how it ends... I meant a temporary buffer on the stack. But a separate allocation sounds even easier.

Quoted 5 lines

Actually I don't care much about which way to take. Use on-stack buffer (if stack usage is not a concern) or local static buffer (caller already held memcg_cache_mutex) is simplest.

But why it's bad to allocate a page for temp use?

GFP_TEMPORARY groups short lived allocations but the mem cache is not an ideal candidate of this type of allocations..

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

It is also not a hot path AFAICS.

Even GFP_ATOMIC for kasprintf would be an improvement IMO.

What about the following (not even compile tested because I do not have cgroup_name in my tree yet):

No, it won't compile. ;)

Somehow expected so as this was just a quick hack to show what I meant. The full patch is bellow (compile time tested on top of for-3.10 branch this time :P)
---
From 7e1f6f0e266a230ced238a9bf2398b4069a6a764 Mon Sep 17 00:00:00 2001
From: Michal Hocko <[email protected]>
Date: Fri, 22 Mar 2013 09:04:58 +0100
Subject: [PATCH] memcg: fix memcg_cache_name() to use cgroup_name()

As cgroup supports rename, it's unsafe to dereference dentry->d_name without proper vfs locks. Fix this by using cgroup_name().

---
 mm/memcontrol.c |   13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
mm/memcontrol.c +9 -4
index 53b8201..5741bf5 100644
@@ -3220,13 +3220,18 @@ static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s)
 	struct dentry *dentry;
 
 	rcu_read_lock();
-	dentry = rcu_dereference(memcg->css.cgroup->dentry);
+	name = kasprintf(GFP_ATOMIC, "%s(%d:%s)", s->name,
+			 memcg_cache_id(memcg), dcgroup_name(memcg->css.cgroup));
 	rcu_read_unlock();
 
-	BUG_ON(dentry == NULL);
+	if (!name) {
+		name = kmalloc(PAGE_SIZE, GFP_KERNEL);
+		rcu_read_lock();
+		name = snprintf(name, PAGE_SIZE, "%s(%d:%s)", s->name,
+				 memcg_cache_id(memcg), dcgroup_name(memcg->css.cgroup));
+		rcu_read_unlock();
 
-	name = kasprintf(GFP_KERNEL, "%s(%d:%s)", s->name,
-			 memcg_cache_id(memcg), dentry->d_name.name);
+	}
 
 	return name;
 }
Signature · 5 lines
1.7.10.4

-- 
Michal Hocko
SUSE Labs
author
#5 lore raw
Quoted 18 lines
Quoted 18 lines
Quoted 17 lines
Quoted 10 lines

Review void mem_cgroup_destroy_cache(struct kmem_cache *cachep) · line 3221

Quoted 7 lines
(quoted diff) +2 -1
@@ -3217,17 +3217,16 @@ void mem_cgroup_destroy_cache(struct kmem_cache *cachep)
 static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s)
 {
 	char *name;
-	struct dentry *dentry;
+
+	name = (char *)__get_free_page(GFP_TEMPORARY);

Ouch. Can we use a static temporary buffer instead?

Quoted 2 lines

This is called from workqueue context so we do not have to be afraid of the deep call chain.

Bahh, I was thinking about two things at the same time and that is how it ends... I meant a temporary buffer on the stack. But a separate allocation sounds even easier.

Quoted 9 lines
Quoted 5 lines

Actually I don't care much about which way to take. Use on-stack buffer (if stack usage is not a concern) or local static buffer (caller already held memcg_cache_mutex) is simplest.

But why it's bad to allocate a page for temp use?

GFP_TEMPORARY groups short lived allocations but the mem cache is not an ideal candidate of this type of allocations..

I'm not sure I'm following you...

char *memcg_cache_name()

{
	char *name = alloc();
	return name;
}

kmem_cache_dup()

{
	name = memcg_cache_name();
	kmem_cache_create_memcg(name);
	free(name);
}

Isn't this a short lived allocation?

Quoted 55 lines
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

It is also not a hot path AFAICS.

Even GFP_ATOMIC for kasprintf would be an improvement IMO.

What about the following (not even compile tested because I do not have cgroup_name in my tree yet):

No, it won't compile. ;)

Somehow expected so as this was just a quick hack to show what I meant. The full patch is bellow (compile time tested on top of for-3.10 branch this time :P)
---

Quoted 1 line

From 7e1f6f0e266a230ced238a9bf2398b4069a6a764 Mon Sep 17 00:00:00 2001

From: Michal Hocko <[email protected]>
Date: Fri, 22 Mar 2013 09:04:58 +0100
Subject: [PATCH] memcg: fix memcg_cache_name() to use cgroup_name()

As cgroup supports rename, it's unsafe to dereference dentry->d_name without proper vfs locks. Fix this by using cgroup_name().

---
 mm/memcontrol.c |   13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
mm/memcontrol.c +9 -4
index 53b8201..5741bf5 100644
@@ -3220,13 +3220,18 @@ static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s)
 	struct dentry *dentry;
 
 	rcu_read_lock();
-	dentry = rcu_dereference(memcg->css.cgroup->dentry);
+	name = kasprintf(GFP_ATOMIC, "%s(%d:%s)", s->name,
+			 memcg_cache_id(memcg), dcgroup_name(memcg->css.cgroup));
 	rcu_read_unlock();
 
-	BUG_ON(dentry == NULL);
+	if (!name) {
+		name = kmalloc(PAGE_SIZE, GFP_KERNEL);
+		rcu_read_lock();
+		name = snprintf(name, PAGE_SIZE, "%s(%d:%s)", s->name,
+				 memcg_cache_id(memcg), dcgroup_name(memcg->css.cgroup));
+		rcu_read_unlock();
 
-	name = kasprintf(GFP_KERNEL, "%s(%d:%s)", s->name,
-			 memcg_cache_id(memcg), dentry->d_name.name);
+	}
 
 	return name;
 }
#6 lore raw
Quoted 11 lines · Li Zefan
Quoted 3 lines

GFP_TEMPORARY groups short lived allocations but the mem cache is not

Quoted 2 lines

an ideal candidate of this type of allocations..

I'm not sure I'm following you...

char *memcg_cache_name()

{
	char *name = alloc();
	return name;
}
Quoted 9 lines

kmem_cache_dup()

{
	name = memcg_cache_name();
	kmem_cache_create_memcg(name);
	free(name);
}

Isn't this a short lived allocation?

Hi,

Thanks for identifying and fixing this.

Li is right. The cache name will live long, but this is because the slab/slub caches will strdup it internally. So the actual memcg allocation is short lived.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#7 lore raw
Quoted 22 lines · Glauber Costa
Quoted 11 lines · Li Zefan
Quoted 3 lines

GFP_TEMPORARY groups short lived allocations but the mem cache is not

Quoted 2 lines

an ideal candidate of this type of allocations..

I'm not sure I'm following you...

char *memcg_cache_name()

{
	char *name = alloc();
	return name;
}
Quoted 9 lines

kmem_cache_dup()

{
	name = memcg_cache_name();
	kmem_cache_create_memcg(name);
	free(name);
}

Isn't this a short lived allocation?

Quoted 7 lines

Hi,

Thanks for identifying and fixing this.

Li is right. The cache name will live long, but this is because the slab/slub caches will strdup it internally. So the actual memcg allocation is short lived.

OK, I have totally missed that. Sorry about the confusion. Then all the churn around the allocation is pointless, no?
What about:
---
From 7ed7f53bb597e8cb40d9ac91ce16142fb60f1e93 Mon Sep 17 00:00:00 2001
From: Michal Hocko <[email protected]>
Date: Fri, 22 Mar 2013 10:22:54 +0100
Subject: [PATCH] memcg: fix memcg_cache_name() to use cgroup_name()

As cgroup supports rename, it's unsafe to dereference dentry->d_name without proper vfs locks. Fix this by using cgroup_name() rather than dentry directly.

Also open code memcg_cache_name because it is called only from kmem_cache_dup which frees the returned name right after kmem_cache_create_memcg makes a copy of it. Such a short-lived allocation doesn't make too much sense. So replace it by a static buffer as kmem_cache_dup is called with memcg_cache_mutex.

---
 mm/memcontrol.c |   33 +++++++++++----------------------
 1 file changed, 11 insertions(+), 22 deletions(-)
mm/memcontrol.c +11 -22
index 53b8201..9452b56 100644
@@ -3214,40 +3214,29 @@ void mem_cgroup_destroy_cache(struct kmem_cache *cachep)
 	schedule_work(&cachep->memcg_params->destroy);
 }
 
-static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s)
-{
-	char *name;
-	struct dentry *dentry;
-
-	rcu_read_lock();
-	dentry = rcu_dereference(memcg->css.cgroup->dentry);
-	rcu_read_unlock();
-
-	BUG_ON(dentry == NULL);
-
-	name = kasprintf(GFP_KERNEL, "%s(%d:%s)", s->name,
-			 memcg_cache_id(memcg), dentry->d_name.name);
-
-	return name;
-}
-
+/*
+ * Called with memcg_cache_mutex held
+ */
 static struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg,
 					 struct kmem_cache *s)
 {
 	char *name;
 	struct kmem_cache *new;
+	static char tmp_name[PAGE_SIZE];
 
-	name = memcg_cache_name(memcg, s);
-	if (!name)
-		return NULL;
+	lockdep_assert_held(&memcg_cache_mutex);
+
+	rcu_read_lock();
+	tmp_name = snprintf(tmp_name, sizeof(tmp_name), "%s(%d:%s)", s->name,
+			 memcg_cache_id(memcg), cgroup_name(memcg->css.cgroup));
+	rcu_read_unlock();
 
-	new = kmem_cache_create_memcg(memcg, name, s->object_size, s->align,
+	new = kmem_cache_create_memcg(memcg, tmp_name, s->object_size, s->align,
 				      (s->flags & ~SLAB_PANIC), s->ctor, s);
 
 	if (new)
 		new->allocflags |= __GFP_KMEMCG;
 
-	kfree(name);
 	return new;
 }
 
Signature · 12 lines
1.7.10.4


-- 
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#8 lore raw
Quoted 27 lines · Michal Hocko
Quoted 26 lines · Glauber Costa
Quoted 11 lines · Li Zefan
Quoted 3 lines

GFP_TEMPORARY groups short lived allocations but the mem cache is not

Quoted 2 lines

an ideal candidate of this type of allocations..

I'm not sure I'm following you...

char *memcg_cache_name()

{
	char *name = alloc();
	return name;
}
Quoted 9 lines

kmem_cache_dup()

{
	name = memcg_cache_name();
	kmem_cache_create_memcg(name);
	free(name);
}

Isn't this a short lived allocation?

Hi,

Thanks for identifying and fixing this.

Quoted 7 lines
Quoted 3 lines

Li is right. The cache name will live long, but this is because the slab/slub caches will strdup it internally. So the actual memcg allocation is short lived.

OK, I have totally missed that. Sorry about the confusion. Then all the churn around the allocation is pointless, no?
What about:

If we're really not concerned about stack, then yes. Even if always running from workqueues, a PAGE_SIZEd stack variable seems risky to me.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#9 lore raw
Quoted 32 lines · Glauber Costa
Quoted 31 lines · Michal Hocko
Quoted 29 lines · Glauber Costa
Quoted 11 lines · Li Zefan
Quoted 3 lines

GFP_TEMPORARY groups short lived allocations but the mem cache is not

Quoted 2 lines

an ideal candidate of this type of allocations..

I'm not sure I'm following you...

char *memcg_cache_name()

{
	char *name = alloc();
	return name;
}
Quoted 9 lines

kmem_cache_dup()

{
	name = memcg_cache_name();
	kmem_cache_create_memcg(name);
	free(name);
}

Isn't this a short lived allocation?

Hi,

Thanks for identifying and fixing this.

Li is right. The cache name will live long, but this is because the slab/slub caches will strdup it internally. So the actual memcg allocation is short lived.

Quoted 6 lines
Quoted 3 lines

OK, I have totally missed that. Sorry about the confusion. Then all the churn around the allocation is pointless, no?
What about:

If we're really not concerned about stack, then yes. Even if always running from workqueues, a PAGE_SIZEd stack variable seems risky to me.

This is not on stack. It is static

Signature · 2 lines
Michal Hocko
SUSE Labs
#10 lore raw
Quoted 33 lines · Michal Hocko
Quoted 32 lines · Glauber Costa
Quoted 31 lines · Michal Hocko
Quoted 29 lines · Glauber Costa
Quoted 11 lines · Li Zefan
Quoted 3 lines

GFP_TEMPORARY groups short lived allocations but the mem cache is not

Quoted 2 lines

an ideal candidate of this type of allocations..

I'm not sure I'm following you...

char *memcg_cache_name()

{
	char *name = alloc();
	return name;
}
Quoted 9 lines

kmem_cache_dup()

{
	name = memcg_cache_name();
	kmem_cache_create_memcg(name);
	free(name);
}

Isn't this a short lived allocation?

Hi,

Thanks for identifying and fixing this.

Li is right. The cache name will live long, but this is because the slab/slub caches will strdup it internally. So the actual memcg allocation is short lived.

Quoted 9 lines
Quoted 6 lines
Quoted 3 lines

OK, I have totally missed that. Sorry about the confusion. Then all the churn around the allocation is pointless, no?
What about:

If we're really not concerned about stack, then yes. Even if always running from workqueues, a PAGE_SIZEd stack variable seems risky to me.

This is not on stack. It is static

Ah, right, I totally missed that. And then you're taking the mutex.

But actually, you don't need to take the mutex. All calls to kmem_cache_dup are protected by the memcg_cache_mutex. So you should be able to just use the buffer without further problems.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#11 lore raw
Quoted 41 lines · Glauber Costa
Quoted 40 lines · Michal Hocko
Quoted 38 lines · Glauber Costa
Quoted 27 lines · Michal Hocko
Quoted 26 lines · Glauber Costa
Quoted 11 lines · Li Zefan
Quoted 3 lines

GFP_TEMPORARY groups short lived allocations but the mem cache is not

Quoted 2 lines

an ideal candidate of this type of allocations..

I'm not sure I'm following you...

char *memcg_cache_name()

{
	char *name = alloc();
	return name;
}
Quoted 9 lines

kmem_cache_dup()

{
	name = memcg_cache_name();
	kmem_cache_create_memcg(name);
	free(name);
}

Isn't this a short lived allocation?

Hi,

Thanks for identifying and fixing this.

Quoted 7 lines
Quoted 3 lines

Li is right. The cache name will live long, but this is because the slab/slub caches will strdup it internally. So the actual memcg allocation is short lived.

OK, I have totally missed that. Sorry about the confusion. Then all the churn around the allocation is pointless, no?
What about:

If we're really not concerned about stack, then yes. Even if always running from workqueues, a PAGE_SIZEd stack variable seems risky to me.

Quoted 6 lines
Quoted 2 lines

This is not on stack. It is static

Ah, right, I totally missed that. And then you're taking the mutex.

But actually, you don't need to take the mutex. All calls to kmem_cache_dup are protected by the memcg_cache_mutex.

Yes and I am not taking that mutex. I've just added lockdep assert to make sure that this still holds true.

Quoted 1 line

So you should be able to just use the buffer without further problems.

Signature · 2 lines
Michal Hocko
SUSE Labs
#12 lore raw
Quoted 44 lines · Michal Hocko
Quoted 43 lines · Glauber Costa
Quoted 42 lines · Michal Hocko
Quoted 32 lines · Glauber Costa
Quoted 31 lines · Michal Hocko
Quoted 29 lines · Glauber Costa
Quoted 11 lines · Li Zefan
Quoted 3 lines

GFP_TEMPORARY groups short lived allocations but the mem cache is not

Quoted 2 lines

an ideal candidate of this type of allocations..

I'm not sure I'm following you...

char *memcg_cache_name()

{
	char *name = alloc();
	return name;
}
Quoted 9 lines

kmem_cache_dup()

{
	name = memcg_cache_name();
	kmem_cache_create_memcg(name);
	free(name);
}

Isn't this a short lived allocation?

Hi,

Thanks for identifying and fixing this.

Li is right. The cache name will live long, but this is because the slab/slub caches will strdup it internally. So the actual memcg allocation is short lived.

Quoted 6 lines
Quoted 3 lines

OK, I have totally missed that. Sorry about the confusion. Then all the churn around the allocation is pointless, no?
What about:

If we're really not concerned about stack, then yes. Even if always running from workqueues, a PAGE_SIZEd stack variable seems risky to me.

This is not on stack. It is static

Quoted 8 lines
Quoted 4 lines

Ah, right, I totally missed that. And then you're taking the mutex.

But actually, you don't need to take the mutex. All calls to kmem_cache_dup are protected by the memcg_cache_mutex.

Yes and I am not taking that mutex. I've just added lockdep assert to make sure that this still holds true.

It is impressive what a busy week does to our brains...

I read the code as lockdep_assert(memcg_cache_mutex), and then later on mutex_lock(&memcg_mutex). But reading again, that was a just an rcu_read_lock(). Good thing it is Friday

You guys can add my Acked-by, and thanks again

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#13 lore raw
Quoted 47 lines · Glauber Costa
Quoted 46 lines · Michal Hocko
Quoted 45 lines · Glauber Costa
Quoted 33 lines · Michal Hocko
Quoted 32 lines · Glauber Costa
Quoted 31 lines · Michal Hocko
Quoted 29 lines · Glauber Costa
Quoted 11 lines · Li Zefan
Quoted 3 lines

GFP_TEMPORARY groups short lived allocations but the mem cache is not

Quoted 2 lines

an ideal candidate of this type of allocations..

I'm not sure I'm following you...

char *memcg_cache_name()

{
	char *name = alloc();
	return name;
}
Quoted 9 lines

kmem_cache_dup()

{
	name = memcg_cache_name();
	kmem_cache_create_memcg(name);
	free(name);
}

Isn't this a short lived allocation?

Hi,

Thanks for identifying and fixing this.

Li is right. The cache name will live long, but this is because the slab/slub caches will strdup it internally. So the actual memcg allocation is short lived.

Quoted 9 lines
Quoted 6 lines
Quoted 3 lines

OK, I have totally missed that. Sorry about the confusion. Then all the churn around the allocation is pointless, no?
What about:

If we're really not concerned about stack, then yes. Even if always running from workqueues, a PAGE_SIZEd stack variable seems risky to me.

This is not on stack. It is static

Ah, right, I totally missed that. And then you're taking the mutex.

Quoted 7 lines
Quoted 6 lines
Quoted 2 lines

But actually, you don't need to take the mutex. All calls to kmem_cache_dup are protected by the memcg_cache_mutex.

Yes and I am not taking that mutex. I've just added lockdep assert to make sure that this still holds true.

It is impressive what a busy week does to our brains...

Tell me something about that.

Quoted 5 lines

I read the code as lockdep_assert(memcg_cache_mutex), and then later on mutex_lock(&memcg_mutex). But reading again, that was a just an rcu_read_lock(). Good thing it is Friday

You guys can add my Acked-by, and thanks again

Li, are you ok to take the page via your tree?

Signature · 2 lines
Michal Hocko
SUSE Labs
author
#14 lore raw
Quoted 8 lines
Quoted 5 lines

I read the code as lockdep_assert(memcg_cache_mutex), and then later on mutex_lock(&memcg_mutex). But reading again, that was a just an rcu_read_lock(). Good thing it is Friday

You guys can add my Acked-by, and thanks again

Li, are you ok to take the page via your tree?

I don't have a git tree in kernel.org. It's Tejun that picks up cgroup patches.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#15 lore raw
Quoted 11 lines · Li Zefan
Quoted 8 lines
Quoted 5 lines

I read the code as lockdep_assert(memcg_cache_mutex), and then later on mutex_lock(&memcg_mutex). But reading again, that was a just an rcu_read_lock(). Good thing it is Friday

You guys can add my Acked-by, and thanks again

Li, are you ok to take the page via your tree?

I don't have a git tree in kernel.org. It's Tejun that picks up cgroup patches.

Oh, I thought both of you push to that tree. Anyway, I will rework the patch and send it again.

Signature · 8 lines
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
author
#16 lore raw
In reply to Michal Hocko
Quoted 19 lines
Quoted 5 lines

Thanks for identifying and fixing this.

Li is right. The cache name will live long, but this is because the slab/slub caches will strdup it internally. So the actual memcg allocation is short lived.

OK, I have totally missed that. Sorry about the confusion. Then all the churn around the allocation is pointless, no?
What about:
---

Quoted 1 line

From 7ed7f53bb597e8cb40d9ac91ce16142fb60f1e93 Mon Sep 17 00:00:00 2001

From: Michal Hocko <[email protected]>
Date: Fri, 22 Mar 2013 10:22:54 +0100
Subject: [PATCH] memcg: fix memcg_cache_name() to use cgroup_name()

As cgroup supports rename, it's unsafe to dereference dentry->d_name without proper vfs locks. Fix this by using cgroup_name() rather than dentry directly.

Quoted 6 lines

Also open code memcg_cache_name because it is called only from kmem_cache_dup which frees the returned name right after kmem_cache_create_memcg makes a copy of it. Such a short-lived allocation doesn't make too much sense. So replace it by a static buffer as kmem_cache_dup is called with memcg_cache_mutex.

I doubt it's a win to add 4K to kernel text size instead of adding a few extra lines of code... but it's up to you.

Quoted 5 lines
---
 mm/memcontrol.c |   33 +++++++++++----------------------
 1 file changed, 11 insertions(+), 22 deletions(-)

...

Quoted 5 lines

static struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg,

mm/memcontrol.c +0 -0
 					 struct kmem_cache *s)
 {
 	char *name;
 	struct kmem_cache *new;

mm/memcontrol.c void mem_cgroup_destroy_cache(struct kmem_cache *cachep) · line 3231

Quoted 10 lines
mm/memcontrol.c +6 -3
+	static char tmp_name[PAGE_SIZE];
 
-	name = memcg_cache_name(memcg, s);
-	if (!name)
-		return NULL;
+	lockdep_assert_held(&memcg_cache_mutex);
+
+	rcu_read_lock();
+	tmp_name = snprintf(tmp_name, sizeof(tmp_name), "%s(%d:%s)", s->name,
+			 memcg_cache_id(memcg), cgroup_name(memcg->css.cgroup));

I guess you didn't turn on CONFIG_MEMCG_KMEM?

snprintf() returns a int value.

Quoted 4 lines
mm/memcontrol.c +1 -0
+	rcu_read_unlock();
 

mm/memcontrol.c void mem_cgroup_destroy_cache(struct kmem_cache *cachep) · line 3241

Quoted 10 lines
mm/memcontrol.c +1 -2
-	new = kmem_cache_create_memcg(memcg, name, s->object_size, s->align,
+	new = kmem_cache_create_memcg(memcg, tmp_name, s->object_size, s->align,
 				      (s->flags & ~SLAB_PANIC), s->ctor, s);
 
 	if (new)
 		new->allocflags |= __GFP_KMEMCG;
 
-	kfree(name);
 	return new;
 }

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#17 lore raw
Quoted 26 lines · Li Zefan
Quoted 19 lines
Quoted 5 lines

Thanks for identifying and fixing this.

Li is right. The cache name will live long, but this is because the slab/slub caches will strdup it internally. So the actual memcg allocation is short lived.

OK, I have totally missed that. Sorry about the confusion. Then all the churn around the allocation is pointless, no?
What about:
---

Quoted 1 line

From 7ed7f53bb597e8cb40d9ac91ce16142fb60f1e93 Mon Sep 17 00:00:00 2001

From: Michal Hocko <[email protected]>
Date: Fri, 22 Mar 2013 10:22:54 +0100
Subject: [PATCH] memcg: fix memcg_cache_name() to use cgroup_name()

As cgroup supports rename, it's unsafe to dereference dentry->d_name without proper vfs locks. Fix this by using cgroup_name() rather than dentry directly.

Quoted 6 lines

Also open code memcg_cache_name because it is called only from kmem_cache_dup which frees the returned name right after kmem_cache_create_memcg makes a copy of it. Such a short-lived allocation doesn't make too much sense. So replace it by a static buffer as kmem_cache_dup is called with memcg_cache_mutex.

Quoted 2 lines

I doubt it's a win to add 4K to kernel text size instead of adding a few extra lines of code... but it's up to you.

I will leave the decision to Glauber. The updated version which uses kmalloc for the static buffer is bellow.

Quoted 13 lines
Quoted 5 lines
---
 mm/memcontrol.c |   33 +++++++++++----------------------
 1 file changed, 11 insertions(+), 22 deletions(-)

...

Quoted 7 lines

static struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg,

(quoted diff) +1 -0
 					 struct kmem_cache *s)
 {
 	char *name;
 	struct kmem_cache *new;
+	static char tmp_name[PAGE_SIZE];
Quoted 10 lines

Review

Quoted 8 lines
(quoted diff) +5 -3
-	name = memcg_cache_name(memcg, s);
-	if (!name)
-		return NULL;
+	lockdep_assert_held(&memcg_cache_mutex);
+
+	rcu_read_lock();
+	tmp_name = snprintf(tmp_name, sizeof(tmp_name), "%s(%d:%s)", s->name,
+			 memcg_cache_id(memcg), cgroup_name(memcg->css.cgroup));

I guess you didn't turn on CONFIG_MEMCG_KMEM?

dohh. Friday effect...

Quoted 1 line

snprintf() returns a int value.

[...]
---
From 6f5d4c08cde5c82ac9432608adf517916ab54634 Mon Sep 17 00:00:00 2001
From: Michal Hocko <[email protected]>
Date: Mon, 25 Mar 2013 10:04:02 +0100
Subject: [PATCH] memcg: fix memcg_cache_name() to use cgroup_name()

As cgroup supports rename, it's unsafe to dereference dentry->d_name without proper vfs locks. Fix this by using cgroup_name() rather than dentry directly.

Also open code memcg_cache_name because it is called only from kmem_cache_dup which frees the returned name right after kmem_cache_create_memcg makes a copy of it. Such a short-lived allocation doesn't make too much sense. So replace it by a static buffer as kmem_cache_dup is called with memcg_cache_mutex.

---
 mm/memcontrol.c |   64 ++++++++++++++++++++++++++++---------------------------
 1 file changed, 33 insertions(+), 31 deletions(-)
mm/memcontrol.c +33 -31
index 53b8201..3a75f2c 100644
@@ -3214,52 +3214,54 @@ void mem_cgroup_destroy_cache(struct kmem_cache *cachep)
 	schedule_work(&cachep->memcg_params->destroy);
 }
 
-static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s)
-{
-	char *name;
-	struct dentry *dentry;
-
-	rcu_read_lock();
-	dentry = rcu_dereference(memcg->css.cgroup->dentry);
-	rcu_read_unlock();
-
-	BUG_ON(dentry == NULL);
-
-	name = kasprintf(GFP_KERNEL, "%s(%d:%s)", s->name,
-			 memcg_cache_id(memcg), dentry->d_name.name);
-
-	return name;
-}
+/*
+ * This lock protects updaters, not readers. We want readers to be as fast as
+ * they can, and they will either see NULL or a valid cache value. Our model
+ * allow them to see NULL, in which case the root memcg will be selected.
+ *
+ * We need this lock because multiple allocations to the same cache from a non
+ * will span more than one worker. Only one of them can create the cache.
+ */
+static DEFINE_MUTEX(memcg_cache_mutex);
 
+/*
+ * Called with memcg_cache_mutex held
+ */
 static struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg,
 					 struct kmem_cache *s)
 {
-	char *name;
 	struct kmem_cache *new;
+	static char *tmp_name = NULL;
 
-	name = memcg_cache_name(memcg, s);
-	if (!name)
-		return NULL;
+	lockdep_assert_held(&memcg_cache_mutex);
+
+	/*
+	 * kmem_cache_create_memcg duplicates the given name and
+	 * cgroup_name for this name requires RCU context.
+	 * This static temporary buffer is used to prevent from
+	 * pointless shortliving allocation.
+	 */
+	if (!tmp_name) {
+		tmp_name = kmalloc(PAGE_SIZE, GFP_KERNEL);
+		WARN_ON_ONCE(!tmp_name);
+		if (!tmp_name)
+			return NULL;
+	}
+
+	rcu_read_lock();
+	snprintf(tmp_name, PAGE_SIZE, "%s(%d:%s)", s->name,
+			 memcg_cache_id(memcg), cgroup_name(memcg->css.cgroup));
+	rcu_read_unlock();
 
-	new = kmem_cache_create_memcg(memcg, name, s->object_size, s->align,
+	new = kmem_cache_create_memcg(memcg, tmp_name, s->object_size, s->align,
 				      (s->flags & ~SLAB_PANIC), s->ctor, s);
 
 	if (new)
 		new->allocflags |= __GFP_KMEMCG;
 
-	kfree(name);
 	return new;
 }
 
-/*
- * This lock protects updaters, not readers. We want readers to be as fast as
- * they can, and they will either see NULL or a valid cache value. Our model
- * allow them to see NULL, in which case the root memcg will be selected.
- *
- * We need this lock because multiple allocations to the same cache from a non
- * will span more than one worker. Only one of them can create the cache.
- */
-static DEFINE_MUTEX(memcg_cache_mutex);
 static struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg,
 						  struct kmem_cache *cachep)
 {
Signature · 6 lines
1.7.10.4


-- 
Michal Hocko
SUSE Labs
author
#18 lore raw
Quoted 16 lines
Quoted 16 lines
Quoted 15 lines
Quoted 1 line

From 7ed7f53bb597e8cb40d9ac91ce16142fb60f1e93 Mon Sep 17 00:00:00 2001

From: Michal Hocko <[email protected]>
Date: Fri, 22 Mar 2013 10:22:54 +0100
Subject: [PATCH] memcg: fix memcg_cache_name() to use cgroup_name()

As cgroup supports rename, it's unsafe to dereference dentry->d_name without proper vfs locks. Fix this by using cgroup_name() rather than dentry directly.

Also open code memcg_cache_name because it is called only from kmem_cache_dup which frees the returned name right after kmem_cache_create_memcg makes a copy of it. Such a short-lived allocation doesn't make too much sense. So replace it by a static buffer as kmem_cache_dup is called with memcg_cache_mutex.

Quoted 6 lines
Quoted 2 lines

I doubt it's a win to add 4K to kernel text size instead of adding a few extra lines of code... but it's up to you.

I will leave the decision to Glauber. The updated version which uses kmalloc for the static buffer is bellow.

I don't have strong preference. Glauber, what's your opinion?

...

mm/memcontrol.c void mem_cgroup_destroy_cache(struct kmem_cache *cachep) · line 3234

Quoted 6 lines

static struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg,

mm/memcontrol.c +1 -1
 					 struct kmem_cache *s)
 {
-	char *name;
 	struct kmem_cache *new;
+	static char *tmp_name = NULL;

(minor nitpick) why not preserve the name "name"

#19 lore raw

On Tue 26-03-13 15:52:32, Li Zefan wrote:
[...]

Quoted 9 lines

...

mm/memcontrol.c void mem_cgroup_destroy_cache(struct kmem_cache *cachep) · line 3234

Quoted 6 lines

static struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg,

mm/memcontrol.c +1 -1
 					 struct kmem_cache *s)
 {
-	char *name;
 	struct kmem_cache *new;
+	static char *tmp_name = NULL;

(minor nitpick) why not preserve the name "name"

I wanted to make it clear that the name is just temporal

Signature · 2 lines
Michal Hocko
SUSE Labs
#20 lore raw
In reply to Michal Hocko
Quoted 7 lines
Quoted 3 lines

I doubt it's a win to add 4K to kernel text size instead of adding a few extra lines of code... but it's up to you.

I will leave the decision to Glauber. The updated version which uses kmalloc for the static buffer is bellow.

I prefer to allocate dynamically here. But although I understand why we need to call cgroup_name, I don't understand what is wrong with kasprintf if we're going to allocate anyway. It will allocate a string just big enough. A PAGE_SIZE'd allocation is a lot more likely to fail.

Now, if we really want to be smart here, we can do something like what I've done for the slub attribute buffers, that can actually have very long values.

allocate a small buffer that will hold 80 % > of the allocations (256 bytes should be enough for most cache names), and if the string is bigger than this, we allocate. Once we allocate, we save it in a static pointer and leave it there. The hope here is that we may be able to live without ever allocating in many systems.

Review

Quoted 7 lines
(quoted diff) +7 -0
+
+	/*
+	 * kmem_cache_create_memcg duplicates the given name and
+	 * cgroup_name for this name requires RCU context.
+	 * This static temporary buffer is used to prevent from
+	 * pointless shortliving allocation.
+	 */

The comment is also no longer true if you don't resort to a static buffer.

The following (untested) patch implements the idea I outlined above.

What do you guys think ?

#21 lore raw
Quoted 22 lines · Glauber Costa
Quoted 7 lines
Quoted 3 lines

I doubt it's a win to add 4K to kernel text size instead of adding a few extra lines of code... but it's up to you.

I will leave the decision to Glauber. The updated version which uses kmalloc for the static buffer is bellow.

I prefer to allocate dynamically here. But although I understand why we need to call cgroup_name, I don't understand what is wrong with kasprintf if we're going to allocate anyway. It will allocate a string just big enough. A PAGE_SIZE'd allocation is a lot more likely to fail.

Now, if we really want to be smart here, we can do something like what I've done for the slub attribute buffers, that can actually have very long values.

allocate a small buffer that will hold 80 % > of the allocations (256 bytes should be enough for most cache names), and if the string is bigger than this, we allocate. Once we allocate, we save it in a static pointer and leave it there. The hope here is that we may be able to live without ever allocating in many systems.

Quoted 8 lines

Review

Quoted 7 lines
(quoted diff) +7 -0
+
+	/*
+	 * kmem_cache_create_memcg duplicates the given name and
+	 * cgroup_name for this name requires RCU context.
+	 * This static temporary buffer is used to prevent from
+	 * pointless shortliving allocation.
+	 */

The comment is also no longer true if you don't resort to a static buffer.

The buffer _is_ static (read global variable hidden with the function scope).

Quoted 3 lines

The following (untested) patch implements the idea I outlined above.

What do you guys think ?

I really do not care which way to fix this.

[...]

Quoted 8 lines
(quoted diff) +5 -2
+static struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg,
+					 struct kmem_cache *s)
 {
-	char *name;
-	struct dentry *dentry;
+	const char *cgname; /* actual cache name */
+	char *name = NULL; /* actual cache name */
+	char buf[256]; /* stack buffer for small allocations */

Review

Quoted 10 lines
(quoted diff) +6 -1
+	int buf_len;
+	static char *buf_name; /* pointer to a page, if we ever need */
+	struct kmem_cache *new;
+
+	lockdep_assert_held(&memcg_cache_mutex);
 
 	rcu_read_lock();
-	dentry = rcu_dereference(memcg->css.cgroup->dentry);
+	cgname = cgroup_name(memcg->css.cgroup);
 	rcu_read_unlock();

cgname is valid only within RCU read lock AFAIU.

Signature · 2 lines
Michal Hocko
SUSE Labs
Acked-by
#22 lore raw
Quoted 32 lines · Michal Hocko
Quoted 22 lines · Glauber Costa
Quoted 7 lines
Quoted 3 lines

I doubt it's a win to add 4K to kernel text size instead of adding a few extra lines of code... but it's up to you.

I will leave the decision to Glauber. The updated version which uses kmalloc for the static buffer is bellow.

I prefer to allocate dynamically here. But although I understand why we need to call cgroup_name, I don't understand what is wrong with kasprintf if we're going to allocate anyway. It will allocate a string just big enough. A PAGE_SIZE'd allocation is a lot more likely to fail.

Now, if we really want to be smart here, we can do something like what I've done for the slub attribute buffers, that can actually have very long values.

allocate a small buffer that will hold 80 % > of the allocations (256 bytes should be enough for most cache names), and if the string is bigger than this, we allocate. Once we allocate, we save it in a static pointer and leave it there. The hope here is that we may be able to live without ever allocating in many systems.

Quoted 8 lines

Review

Quoted 7 lines
(quoted diff) +7 -0
+
+	/*
+	 * kmem_cache_create_memcg duplicates the given name and
+	 * cgroup_name for this name requires RCU context.
+	 * This static temporary buffer is used to prevent from
+	 * pointless shortliving allocation.
+	 */

The comment is also no longer true if you don't resort to a static buffer.

Quoted 3 lines

The buffer _is_ static (read global variable hidden with the function scope).

Although correct, it is a bit misleading. It is static in the sense it is held by a static variable. But it is acquired by kmalloc...

In any way, this is a tiny detail.

FWIW, I am fine with the patch you provided:

We could go seeing how big those allocations are in practice, but I doubt it is worth the trouble.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#23 lore raw
Quoted 9 lines

Although correct, it is a bit misleading. It is static in the sense it is held by a static variable. But it is acquired by kmalloc...

In any way, this is a tiny detail.

FWIW, I am fine with the patch you provided:

Michal, could you resend your final patch to Tejun in a new mail thread? There are quite a few different patches inlined in this thread.

#24 lore raw
Quoted 5 lines · Li Zefan
Quoted 5 lines

Although correct, it is a bit misleading. It is static in the sense it is held by a static variable. But it is acquired by kmalloc...

In any way, this is a tiny detail.

Quoted 7 lines
Quoted 4 lines

FWIW, I am fine with the patch you provided:

Michal, could you resend your final patch to Tejun in a new mail thread? There are quite a few different patches inlined in this thread.

Done.

Signature · 8 lines
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>