Skip to contentSkip to conversation

memcg: remove -EINTR at rmdir()

PATCH In review Kamezawa Hiroyuki 3 participants 12 messages Jun 18, 2012 – Jun 22, 2012

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/2 memcg: remove -EINTR at rmdir()

2 follow-up patches for "memcg: move charges to root cgroup if use_hierarchy=0", developped/tested onto memcg-devel tree. Maybe no HUNK with -next and -mm.... -Kame
==
memcg: remove -EINTR at rmdir()

By commit "memcg: move charges to root cgroup if use_hierarchy=0", no memory reclaiming will occur at removing memory cgroup.

So, we don't need to take care of user interrupt by signal. This patch removes it.
(*) If -EINTR is returned here, cgroup will show WARNING.

---
 mm/memcontrol.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)
mm/memcontrol.c +0 -3
index 0623300..cf8a0f6 100644
@@ -3890,9 +3890,6 @@ move_account:
 		ret = -EBUSY;
 		if (cgroup_task_count(cgrp) || !list_empty(&cgrp->children))
 			goto out;
-		ret = -EINTR;
-		if (signal_pending(current))
-			goto out;
 		/* This is for making all *used* pages to be on LRU. */
 		lru_add_drain_all();
 		drain_all_stock_sync(memcg);
Signature · 1 line
1.7.4.1
#1 lore raw

PATCH 2/2 memcg: clean up force_empty_list() return value check

By commit "memcg: move charges to root cgroup if use_hierarchy=0" mem_cgroup_move_parent() only returns -EBUSY, -EINVAL. So, we can remove -ENOMEM and -EINTR checks.

---
 mm/memcontrol.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)
mm/memcontrol.c +0 -5
index cf8a0f6..726b7c6 100644
@@ -3847,8 +3847,6 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 		pc = lookup_page_cgroup(page);
 
 		ret = mem_cgroup_move_parent(page, pc, memcg, GFP_KERNEL);
-		if (ret == -ENOMEM || ret == -EINTR)
-			break;
 
 		if (ret == -EBUSY || ret == -EINVAL) {
 			/* found lock contention or "pc" is obsolete. */
@@ -3910,9 +3908,6 @@ move_account:
 		}
 		mem_cgroup_end_move(memcg);
 		memcg_oom_recover(memcg);
-		/* it seems parent cgroup doesn't have enough mem */
-		if (ret == -ENOMEM)
-			goto try_to_free;
 		cond_resched();
 	/* "ret" should also be checked to ensure all lists are empty. */
 	} while (res_counter_read_u64(&memcg->res, RES_USAGE) > 0 || ret);
Signature · 1 line
1.7.4.1
Acked-by on v1 2/2
#2 lore raw

Re: [PATCH 2/2] memcg: clean up force_empty_list() return value check

Quoted 6 lines · KAMEZAWA Hiroyuki

By commit "memcg: move charges to root cgroup if use_hierarchy=0" mem_cgroup_move_parent() only returns -EBUSY, -EINVAL. So, we can remove -ENOMEM and -EINTR checks.

Quoted 35 lines
---
 mm/memcontrol.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)
mm/memcontrol.c +0 -5
index cf8a0f6..726b7c6 100644
@@ -3847,8 +3847,6 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 		pc = lookup_page_cgroup(page);
 
 		ret = mem_cgroup_move_parent(page, pc, memcg, GFP_KERNEL);
-		if (ret == -ENOMEM || ret == -EINTR)
-			break;
 
 		if (ret == -EBUSY || ret == -EINVAL) {
 			/* found lock contention or "pc" is obsolete. */
@@ -3910,9 +3908,6 @@ move_account:
 		}
 		mem_cgroup_end_move(memcg);
 		memcg_oom_recover(memcg);
-		/* it seems parent cgroup doesn't have enough mem */
-		if (ret == -ENOMEM)
-			goto try_to_free;
 		cond_resched();
 	/* "ret" should also be checked to ensure all lists are empty. */
 	} while (res_counter_read_u64(&memcg->res, RES_USAGE) > 0 || ret);
Signature · 7 lines
1.7.4.1


--
To unsubscribe from this list: send the line "unsubscribe cgroups" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Signature · 6 lines
Michal Hocko
SUSE Labs
SUSE LINUX s.r.o.
Lihovarska 1060/12
190 00 Praha 9    
Czech Republic
maintainer
#3 lore raw

Re: [PATCH 2/2] memcg: clean up force_empty_list() return value check

In reply to Kamezawa Hiroyuki
Quoted 15 lines · On Mon, 18 Jun 2012 20:59:44 +0900 Kamezawa Hiroyuki…

By commit "memcg: move charges to root cgroup if use_hierarchy=0" mem_cgroup_move_parent() only returns -EBUSY, -EINVAL. So, we can remove -ENOMEM and -EINTR checks.

---
 mm/memcontrol.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)
mm/memcontrol.c +0 -0
index cf8a0f6..726b7c6 100644

mm/memcontrol.c static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg, · line 3851

Quoted 7 lines
mm/memcontrol.c +0 -2
@@ -3847,8 +3847,6 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 		pc = lookup_page_cgroup(page);
 
 		ret = mem_cgroup_move_parent(page, pc, memcg, GFP_KERNEL);
-		if (ret == -ENOMEM || ret == -EINTR)
-			break;
 
 		if (ret == -EBUSY || ret == -EINVAL) {

This looks a bit fragile - if mem_cgroup_move_parent() is later changed (intentionally or otherwise!) to return -Esomethingelse then mem_cgroup_force_empty_list() will subtly break. Why not just do

		if (ret < 0)

here?

--
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

Re: [PATCH 2/2] memcg: clean up force_empty_list() return value check

Quoted 24 lines · Andrew Morton
Quoted 21 lines · On Mon, 18 Jun 2012 20:59:44 +0900 Kamezawa…

By commit "memcg: move charges to root cgroup if use_hierarchy=0" mem_cgroup_move_parent() only returns -EBUSY, -EINVAL. So, we can remove -ENOMEM and -EINTR checks.

---
  mm/memcontrol.c |    5 -----
  1 files changed, 0 insertions(+), 5 deletions(-)
mm/memcontrol.c +0 -2
index cf8a0f6..726b7c6 100644
@@ -3847,8 +3847,6 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
  		pc = lookup_page_cgroup(page);
 
  		ret = mem_cgroup_move_parent(page, pc, memcg, GFP_KERNEL);
-		if (ret == -ENOMEM || ret == -EINTR)
-			break;
 
Quoted 8 lines

mm/memcontrol.c static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg, · line 3851

Quoted 1 line
mm/memcontrol.c +0 -0
  		if (ret == -EBUSY || ret == -EINVAL) {

This looks a bit fragile - if mem_cgroup_move_parent() is later changed (intentionally or otherwise!) to return -Esomethingelse then mem_cgroup_force_empty_list() will subtly break. Why not just do

		if (ret<  0)

You're right. I'm sorry I haven't done enough clean-ups.
I made 2 more patches...I'll repost/remake all paches if it's better. one more patch will follow this email.
==
From eee5f31fc6378da19705de7187bb3f219ef6d7f6 Mon Sep 17 00:00:00 2001
From: KAMEZAWA Hiroyuki <[email protected]>
Date: Thu, 21 Jun 2012 17:25:04 +0900
Subject: [PATCH 1/2] mem_cgroup_move_parent() doesn't need gfp_mask.

---
 mm/memcontrol.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)
mm/memcontrol.c +2 -3
index 76d83a5..90a2ad4 100644
@@ -2662,8 +2662,7 @@ out:
 
 static int mem_cgroup_move_parent(struct page *page,
 				  struct page_cgroup *pc,
-				  struct mem_cgroup *child,
-				  gfp_t gfp_mask)
+				  struct mem_cgroup *child)
 {
 	struct mem_cgroup *parent;
 	unsigned int nr_pages;
@@ -3837,7 +3836,7 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 
 		pc = lookup_page_cgroup(page);
 
-		ret = mem_cgroup_move_parent(page, pc, memcg, GFP_KERNEL);
+		ret = mem_cgroup_move_parent(page, pc, memcg);
 
 		if (ret == -EBUSY || ret == -EINVAL) {
 			/* found lock contention or "pc" is obsolete. */
Signature · 17 lines
1.7.4.1











--
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>
#5 lore raw

Re: [PATCH 2/2] memcg: clean up force_empty_list() return value check

You're right and I think this will be much cleaner. ==

From 9b6224616282d74838b393485eb7c9215f546ec9 Mon Sep 17 00:00:00 2001
From: KAMEZAWA Hiroyuki <[email protected]>
Date: Thu, 21 Jun 2012 17:28:55 +0900
Subject: [PATCH 2/2] memcg: make mem_cgroup_force_empty_list() as boolean function

Now, mem_cgroup_force_empty_list() just returns 0 or -EBUSY and -EBUSY is just indicating 'you need to retry.'.
This patch makes mem_cgroup_force_empty_list() as boolean function and make the logic simpler.

---
 mm/memcontrol.c |   13 +++----------
 1 files changed, 3 insertions(+), 10 deletions(-)
mm/memcontrol.c +3 -10
index 90a2ad4..767440c 100644
@@ -3797,7 +3797,7 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
  * This routine traverse page_cgroup in given list and drop them all.
  * *And* this routine doesn't reclaim page itself, just removes page_cgroup.
  */
-static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
+static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 				int node, int zid, enum lru_list lru)
 {
 	struct mem_cgroup_per_zone *mz;
@@ -3805,7 +3805,6 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 	struct list_head *list;
 	struct page *busy;
 	struct zone *zone;
-	int ret = 0;
 
 	zone = &NODE_DATA(node)->node_zones[zid];
 	mz = mem_cgroup_zoneinfo(memcg, node, zid);
@@ -3819,7 +3818,6 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 		struct page_cgroup *pc;
 		struct page *page;
 
-		ret = 0;
 		spin_lock_irqsave(&zone->lru_lock, flags);
 		if (list_empty(list)) {
 			spin_unlock_irqrestore(&zone->lru_lock, flags);
@@ -3836,19 +3834,14 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 
 		pc = lookup_page_cgroup(page);
 
-		ret = mem_cgroup_move_parent(page, pc, memcg);
-
-		if (ret == -EBUSY || ret == -EINVAL) {
+		if (mem_cgroup_move_parent(page, pc, memcg)) {
 			/* found lock contention or "pc" is obsolete. */
 			busy = page;
 			cond_resched();
 		} else
 			busy = NULL;
 	}
-
-	if (!ret && !list_empty(list))
-		return -EBUSY;
-	return ret;
+	return !list_empty(list);
 }
 
 /*
Signature · 1 line
1.7.4.1
maintainer
#6 lore raw

Re: [PATCH 2/2] memcg: clean up force_empty_list() return value check

Quoted 5 lines · On Thu, 21 Jun 2012 17:17:01 +0900 Kamezawa Hiroyuki…

Now, mem_cgroup_force_empty_list() just returns 0 or -EBUSY and -EBUSY is just indicating 'you need to retry.'.
This patch makes mem_cgroup_force_empty_list() as boolean function and make the logic simpler.

For some reason I'm having trouble applying these patches - many rejects, need to massage it in by hand.

mm/memcontrol.c unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, · line 3801

Quoted 9 lines
mm/memcontrol.c +1 -1
@@ -3797,7 +3797,7 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
   * This routine traverse page_cgroup in given list and drop them all.
   * *And* this routine doesn't reclaim page itself, just removes page_cgroup.
   */
-static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
+static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
  				int node, int zid, enum lru_list lru)

Let's document the return value. The mem_cgroup_force_empty_list() comment is a mess so I tried to help it a bit. How does this look?

mm/memcontrol.c renamed from mm/memcontrol.c~memcg-make-mem_cgroup_force_empty_list-return-bool-fix +4 -2
@@ -3609,8 +3609,10 @@ unsigned long mem_cgroup_soft_limit_recl
 }
 
 /*
- * This routine traverse page_cgroup in given list and drop them all.
- * *And* this routine doesn't reclaim page itself, just removes page_cgroup.
+ * Traverse a specified page_cgroup list and try to drop them all.  This doesn't
+ * reclaim the pages page themselves - it just removes the page_cgroups.
+ * Returns true if some page_cgroups were not freed, indicating that the caller
+ * must retry this operation.
  */
 static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 				int node, int zid, enum lru_list lru)

_

#7 lore raw

Re: [PATCH 2/2] memcg: clean up force_empty_list() return value check

Quoted 12 lines · Andrew Morton
Quoted 5 lines · On Thu, 21 Jun 2012 17:17:01 +0900 Kamezawa…

Now, mem_cgroup_force_empty_list() just returns 0 or -EBUSY and -EBUSY is just indicating 'you need to retry.'.
This patch makes mem_cgroup_force_empty_list() as boolean function and make the logic simpler.

For some reason I'm having trouble applying these patches - many rejects, need to massage it in by hand.

Oh, sorry. Is it space breakage or some ? (I had mailer troubles in the last week..) Or, maybe, my tree/patch queue was too old.
I'll rebased to new -mm tree when I post new patch.

Quoted 28 lines

mm/memcontrol.c unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, · line 3801

Quoted 9 lines
mm/memcontrol.c +1 -1
@@ -3797,7 +3797,7 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
    * This routine traverse page_cgroup in given list and drop them all.
    * *And* this routine doesn't reclaim page itself, just removes page_cgroup.
    */
-static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
+static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
   				int node, int zid, enum lru_list lru)

Let's document the return value. The mem_cgroup_force_empty_list() comment is a mess so I tried to help it a bit. How does this look?

mm/memcontrol.c renamed from mm/memcontrol.c~memcg-make-mem_cgroup_force_empty_list-return-bool-fix +4 -2
@@ -3609,8 +3609,10 @@ unsigned long mem_cgroup_soft_limit_recl
  }
 
  /*
- * This routine traverse page_cgroup in given list and drop them all.
- * *And* this routine doesn't reclaim page itself, just removes page_cgroup.
+ * Traverse a specified page_cgroup list and try to drop them all.  This doesn't
+ * reclaim the pages page themselves - it just removes the page_cgroups.
+ * Returns true if some page_cgroups were not freed, indicating that the caller
+ * must retry this operation.
   */
  static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
  				int node, int zid, enum lru_list lru)
Quoted 1 line

_

Seems nice! Thank you very much.

Regards,
-Kame

Acked-by on v1 1/2
#8 lore raw
In reply to Kamezawa Hiroyuki
Quoted 8 lines · KAMEZAWA Hiroyuki

2 follow-up patches for "memcg: move charges to root cgroup if use_hierarchy=0", developped/tested onto memcg-devel tree. Maybe no HUNK with -next and -mm.... -Kame
==
memcg: remove -EINTR at rmdir()

By commit "memcg: move charges to root cgroup if use_hierarchy=0", no memory reclaiming will occur at removing memory cgroup.

OK, so the there are only 2 reasons why move_parent could fail in this path. 1) it races with somebody else who is uncharging or moving the charge and 2) THP split.
1) works for us and 2) doens't seem to be serious enough to expect that it would stall rmdir on the group for unbound amount of time so the change is safe (can we make this into the changelog please?).

Quoted 5 lines

So, we don't need to take care of user interrupt by signal. This patch removes it.
(*) If -EINTR is returned here, cgroup will show WARNING.

Quoted 26 lines
---
 mm/memcontrol.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)
mm/memcontrol.c +0 -3
index 0623300..cf8a0f6 100644
@@ -3890,9 +3890,6 @@ move_account:
 		ret = -EBUSY;
 		if (cgroup_task_count(cgrp) || !list_empty(&cgrp->children))
 			goto out;
-		ret = -EINTR;
-		if (signal_pending(current))
-			goto out;
 		/* This is for making all *used* pages to be on LRU. */
 		lru_add_drain_all();
 		drain_all_stock_sync(memcg);
Signature · 7 lines
1.7.4.1


--
To unsubscribe from this list: send the line "unsubscribe cgroups" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Signature · 12 lines
Michal Hocko
SUSE Labs
SUSE LINUX s.r.o.
Lihovarska 1060/12
190 00 Praha 9    
Czech Republic

--
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 10 lines · Michal Hocko
Quoted 8 lines · KAMEZAWA Hiroyuki

2 follow-up patches for "memcg: move charges to root cgroup if use_hierarchy=0", developped/tested onto memcg-devel tree. Maybe no HUNK with -next and -mm.... -Kame
==
memcg: remove -EINTR at rmdir()

By commit "memcg: move charges to root cgroup if use_hierarchy=0", no memory reclaiming will occur at removing memory cgroup.

Quoted 7 lines

OK, so the there are only 2 reasons why move_parent could fail in this path. 1) it races with somebody else who is uncharging or moving the charge and 2) THP split.
1) works for us and 2) doens't seem to be serious enough to expect that it would stall rmdir on the group for unbound amount of time so the change is safe (can we make this into the changelog please?).

Yes. But the failure of move_parent() (-EBUSY) will be retried.

Remaining problems are
- attaching task while pre_destroy() is called.
- creating child cgroup while pre_destroy() is called.

I think I need to make a patch for cgroup layer as I previously posted. I'd like to try again.

Thanks,
-Kame

--
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>

#10 lore raw
Quoted 19 lines · KAMEZAWA Hiroyuki
Quoted 10 lines · Michal Hocko
Quoted 8 lines · KAMEZAWA Hiroyuki

2 follow-up patches for "memcg: move charges to root cgroup if use_hierarchy=0", developped/tested onto memcg-devel tree. Maybe no HUNK with -next and -mm.... -Kame
==
memcg: remove -EINTR at rmdir()

By commit "memcg: move charges to root cgroup if use_hierarchy=0", no memory reclaiming will occur at removing memory cgroup.

Quoted 7 lines

OK, so the there are only 2 reasons why move_parent could fail in this path. 1) it races with somebody else who is uncharging or moving the charge and 2) THP split.
1) works for us and 2) doens't seem to be serious enough to expect that it would stall rmdir on the group for unbound amount of time so the change is safe (can we make this into the changelog please?).

Quoted 5 lines

Yes. But the failure of move_parent() (-EBUSY) will be retried.

Remaining problems are
- attaching task while pre_destroy() is called.
- creating child cgroup while pre_destroy() is called.

I don't know why but I thought that tasks and subgroups are not alowed when pre_destroy is called. If this is possible then we probably want to check for pending signals or at least add cond_resched.

Quoted 7 lines

I think I need to make a patch for cgroup layer as I previously posted. I'd like to try again.

Thanks,
-Kame

Signature · 12 lines
Michal Hocko
SUSE Labs
SUSE LINUX s.r.o.
Lihovarska 1060/12
190 00 Praha 9    
Czech Republic

--
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 22 lines · Michal Hocko
Quoted 21 lines · KAMEZAWA Hiroyuki
Quoted 10 lines · Michal Hocko
Quoted 8 lines · KAMEZAWA Hiroyuki

2 follow-up patches for "memcg: move charges to root cgroup if use_hierarchy=0", developped/tested onto memcg-devel tree. Maybe no HUNK with -next and -mm.... -Kame
==
memcg: remove -EINTR at rmdir()

By commit "memcg: move charges to root cgroup if use_hierarchy=0", no memory reclaiming will occur at removing memory cgroup.

Quoted 7 lines

OK, so the there are only 2 reasons why move_parent could fail in this path. 1) it races with somebody else who is uncharging or moving the charge and 2) THP split.
1) works for us and 2) doens't seem to be serious enough to expect that it would stall rmdir on the group for unbound amount of time so the change is safe (can we make this into the changelog please?).

Yes. But the failure of move_parent() (-EBUSY) will be retried.

Quoted 7 lines
Quoted 3 lines

Remaining problems are
- attaching task while pre_destroy() is called.
- creating child cgroup while pre_destroy() is called.

I don't know why but I thought that tasks and subgroups are not alowed when pre_destroy is called. If this is possible then we probably want to check for pending signals or at least add cond_resched.

Now, pre_destroy() call is done as

	lock_cgroup_mutex();
	do some pre-check, no child, no tasks.
	unlock_cgroup_mutex();

	->pre_destroy()

	lock_cgroup_mutex()
	check css's refcnt....

What I take care of now is following case.
CPU A CPU-B
unlock_cgroup_mutex()
->pre_destroy()

<delay by something> attach new task
add new charge detach the task
lock_cgroup_mutex()
check rss' refcnt

This will cause account leak even if I think this will not happen in the real world. I'd like to disable attach task.

Now, our ->pre_destroy() is quite fast because we don't have no memory reclaim. I believe we can call ->pre_destroy() without dropping cgroup_mutex.

	lock_cgroup_mutex()
	do pre-check

	->pre_destroy()

	check css's refcnt

I think this is straightforward. I'd like to post a patch. Thanks,
-Kame

--
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>