All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch 00/11] mm: memcg: charge/uncharge improvements
@ 2012-07-05  0:44 ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Hello,

the biggest thing is probably #1, no longer trying (and failing) to
charge replacement pages during migration and thus compaction.  The
rest is cleanups and tiny optimizations that move some checks out of
the charge and uncharge core paths that do not apply to all types of
pages alike.

 include/linux/memcontrol.h |   11 +--
 mm/memcontrol.c            |  205 +++++++++++++++++++++++---------------------
 mm/migrate.c               |   27 ++-----
 mm/shmem.c                 |   11 ++-
 mm/swapfile.c              |    3 +-
 5 files changed, 124 insertions(+), 133 deletions(-)


^ permalink raw reply	[flat|nested] 90+ messages in thread

* [patch 00/11] mm: memcg: charge/uncharge improvements
@ 2012-07-05  0:44 ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Hello,

the biggest thing is probably #1, no longer trying (and failing) to
charge replacement pages during migration and thus compaction.  The
rest is cleanups and tiny optimizations that move some checks out of
the charge and uncharge core paths that do not apply to all types of
pages alike.

 include/linux/memcontrol.h |   11 +--
 mm/memcontrol.c            |  205 +++++++++++++++++++++++---------------------
 mm/migrate.c               |   27 ++-----
 mm/shmem.c                 |   11 ++-
 mm/swapfile.c              |    3 +-
 5 files changed, 124 insertions(+), 133 deletions(-)

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [patch 01/11] mm: memcg: fix compaction/migration failing due to memcg limits
  2012-07-05  0:44 ` Johannes Weiner
@ 2012-07-05  0:44   ` Johannes Weiner
  -1 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Compaction (and page migration in general) can currently be hindered
through pages being owned by memory cgroups that are at their limits
and unreclaimable.

The reason is that the replacement page is being charged against the
limit while the page being replaced is also still charged.  But this
seems unnecessary, given that only one of the two pages will still be
in use after migration finishes.

This patch changes the memcg migration sequence so that the
replacement page is not charged.  Whatever page is still in use after
successful or failed migration gets to keep the charge of the page
that was going to be replaced.

Reported-by: David Rientjes <rientjes@google.com>
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 include/linux/memcontrol.h |   11 +++----
 mm/memcontrol.c            |   67 +++++++++++++++++++++++--------------------
 mm/migrate.c               |   27 ++++--------------
 3 files changed, 47 insertions(+), 58 deletions(-)

diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 1700762..8444f64 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -100,9 +100,9 @@ int mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *cgroup)
 
 extern struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *memcg);
 
-extern int
-mem_cgroup_prepare_migration(struct page *page,
-	struct page *newpage, struct mem_cgroup **memcgp, gfp_t gfp_mask);
+extern void
+mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
+			     struct mem_cgroup **memcgp);
 extern void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 	struct page *oldpage, struct page *newpage, bool migration_ok);
 
@@ -279,11 +279,10 @@ static inline struct cgroup_subsys_state
 	return NULL;
 }
 
-static inline int
+static inline void
 mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
-	struct mem_cgroup **memcgp, gfp_t gfp_mask)
+			     struct mem_cgroup **memcgp)
 {
-	return 0;
 }
 
 static inline void mem_cgroup_end_migration(struct mem_cgroup *memcg,
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index b11fb2f..4ea19c6 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2909,7 +2909,8 @@ static void mem_cgroup_do_uncharge(struct mem_cgroup *memcg,
  * uncharge if !page_mapped(page)
  */
 static struct mem_cgroup *
-__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
+__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype,
+			     bool end_migration)
 {
 	struct mem_cgroup *memcg = NULL;
 	unsigned int nr_pages = 1;
@@ -2953,7 +2954,16 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
 		/* fallthrough */
 	case MEM_CGROUP_CHARGE_TYPE_DROP:
 		/* See mem_cgroup_prepare_migration() */
-		if (page_mapped(page) || PageCgroupMigration(pc))
+		if (page_mapped(page))
+			goto unlock_out;
+		/*
+		 * Pages under migration may not be uncharged.  But
+		 * end_migration() /must/ be the one uncharging the
+		 * unused post-migration page and so it has to call
+		 * here with the migration bit still set.  See the
+		 * res_counter handling below.
+		 */
+		if (!end_migration && PageCgroupMigration(pc))
 			goto unlock_out;
 		break;
 	case MEM_CGROUP_CHARGE_TYPE_SWAPOUT:
@@ -2987,7 +2997,12 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
 		mem_cgroup_swap_statistics(memcg, true);
 		mem_cgroup_get(memcg);
 	}
-	if (!mem_cgroup_is_root(memcg))
+	/*
+	 * Migration does not charge the res_counter for the
+	 * replacement page, so leave it alone when phasing out the
+	 * page that is unused after the migration.
+	 */
+	if (!end_migration && !mem_cgroup_is_root(memcg))
 		mem_cgroup_do_uncharge(memcg, nr_pages, ctype);
 
 	return memcg;
@@ -3003,14 +3018,14 @@ void mem_cgroup_uncharge_page(struct page *page)
 	if (page_mapped(page))
 		return;
 	VM_BUG_ON(page->mapping && !PageAnon(page));
-	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON);
+	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false);
 }
 
 void mem_cgroup_uncharge_cache_page(struct page *page)
 {
 	VM_BUG_ON(page_mapped(page));
 	VM_BUG_ON(page->mapping);
-	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE);
+	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false);
 }
 
 /*
@@ -3074,7 +3089,7 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
 	if (!swapout) /* this was a swap cache but the swap is unused ! */
 		ctype = MEM_CGROUP_CHARGE_TYPE_DROP;
 
-	memcg = __mem_cgroup_uncharge_common(page, ctype);
+	memcg = __mem_cgroup_uncharge_common(page, ctype, false);
 
 	/*
 	 * record memcg information,  if swapout && memcg != NULL,
@@ -3164,19 +3179,18 @@ static inline int mem_cgroup_move_swap_account(swp_entry_t entry,
  * Before starting migration, account PAGE_SIZE to mem_cgroup that the old
  * page belongs to.
  */
-int mem_cgroup_prepare_migration(struct page *page,
-	struct page *newpage, struct mem_cgroup **memcgp, gfp_t gfp_mask)
+void mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
+				  struct mem_cgroup **memcgp)
 {
 	struct mem_cgroup *memcg = NULL;
 	struct page_cgroup *pc;
 	enum charge_type ctype;
-	int ret = 0;
 
 	*memcgp = NULL;
 
 	VM_BUG_ON(PageTransHuge(page));
 	if (mem_cgroup_disabled())
-		return 0;
+		return;
 
 	pc = lookup_page_cgroup(page);
 	lock_page_cgroup(pc);
@@ -3221,24 +3235,9 @@ int mem_cgroup_prepare_migration(struct page *page,
 	 * we return here.
 	 */
 	if (!memcg)
-		return 0;
+		return;
 
 	*memcgp = memcg;
-	ret = __mem_cgroup_try_charge(NULL, gfp_mask, 1, memcgp, false);
-	css_put(&memcg->css);/* drop extra refcnt */
-	if (ret) {
-		if (PageAnon(page)) {
-			lock_page_cgroup(pc);
-			ClearPageCgroupMigration(pc);
-			unlock_page_cgroup(pc);
-			/*
-			 * The old page may be fully unmapped while we kept it.
-			 */
-			mem_cgroup_uncharge_page(page);
-		}
-		/* we'll need to revisit this error code (we have -EINTR) */
-		return -ENOMEM;
-	}
 	/*
 	 * We charge new page before it's used/mapped. So, even if unlock_page()
 	 * is called before end_migration, we can catch all events on this new
@@ -3251,8 +3250,12 @@ int mem_cgroup_prepare_migration(struct page *page,
 		ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
 	else
 		ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
+	/*
+	 * The page is committed to the memcg, but it's not actually
+	 * charged to the res_counter since we plan on replacing the
+	 * old one and only one page is going to be left afterwards.
+	 */
 	__mem_cgroup_commit_charge(memcg, newpage, 1, ctype, false);
-	return ret;
 }
 
 /* remove redundant charge if migration failed*/
@@ -3274,6 +3277,12 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 		used = newpage;
 		unused = oldpage;
 	}
+	anon = PageAnon(used);
+	__mem_cgroup_uncharge_common(unused,
+		anon ? MEM_CGROUP_CHARGE_TYPE_ANON
+		     : MEM_CGROUP_CHARGE_TYPE_CACHE,
+		true);
+	css_put(&memcg->css);
 	/*
 	 * We disallowed uncharge of pages under migration because mapcount
 	 * of the page goes down to zero, temporarly.
@@ -3283,10 +3292,6 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 	lock_page_cgroup(pc);
 	ClearPageCgroupMigration(pc);
 	unlock_page_cgroup(pc);
-	anon = PageAnon(used);
-	__mem_cgroup_uncharge_common(unused,
-		anon ? MEM_CGROUP_CHARGE_TYPE_ANON
-		     : MEM_CGROUP_CHARGE_TYPE_CACHE);
 
 	/*
 	 * If a page is a file cache, radix-tree replacement is very atomic
diff --git a/mm/migrate.c b/mm/migrate.c
index 8137aea..aa06bf4 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -687,7 +687,6 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
 {
 	int rc = -EAGAIN;
 	int remap_swapcache = 1;
-	int charge = 0;
 	struct mem_cgroup *mem;
 	struct anon_vma *anon_vma = NULL;
 
@@ -729,12 +728,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
 	}
 
 	/* charge against new page */
-	charge = mem_cgroup_prepare_migration(page, newpage, &mem, GFP_KERNEL);
-	if (charge == -ENOMEM) {
-		rc = -ENOMEM;
-		goto unlock;
-	}
-	BUG_ON(charge);
+	mem_cgroup_prepare_migration(page, newpage, &mem);
 
 	if (PageWriteback(page)) {
 		/*
@@ -824,8 +818,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
 		put_anon_vma(anon_vma);
 
 uncharge:
-	if (!charge)
-		mem_cgroup_end_migration(mem, page, newpage, rc == 0);
+	mem_cgroup_end_migration(mem, page, newpage, rc == 0);
 unlock:
 	unlock_page(page);
 out:
@@ -1519,10 +1512,9 @@ migrate_misplaced_page(struct page *page, struct mm_struct *mm, int node)
 {
 	struct page *oldpage = page, *newpage;
 	struct address_space *mapping = page_mapping(page);
-	struct mem_cgroup *mcg;
+	struct mem_cgroup *memcg;
 	unsigned int gfp;
 	int rc = 0;
-	int charge = -ENOMEM;
 
 	VM_BUG_ON(!PageLocked(page));
 	VM_BUG_ON(page_mapcount(page));
@@ -1556,12 +1548,7 @@ migrate_misplaced_page(struct page *page, struct mm_struct *mm, int node)
 	if (!trylock_page(newpage))
 		BUG();		/* new page should be unlocked!!! */
 
-	// XXX hnaz, is this right?
-	charge = mem_cgroup_prepare_migration(page, newpage, &mcg, gfp);
-	if (charge == -ENOMEM) {
-		rc = charge;
-		goto out;
-	}
+	mem_cgroup_prepare_migration(page, newpage, &memcg);
 
 	newpage->index = page->index;
 	newpage->mapping = page->mapping;
@@ -1581,11 +1568,9 @@ migrate_misplaced_page(struct page *page, struct mm_struct *mm, int node)
 		page = newpage;
 	}
 
+	mem_cgroup_end_migration(memcg, oldpage, newpage, !rc);
 out:
-	if (!charge)
-		mem_cgroup_end_migration(mcg, oldpage, newpage, !rc);
-
-       if (oldpage != page)
+	if (oldpage != page)
                put_page(oldpage);
 
 	if (rc) {
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 01/11] mm: memcg: fix compaction/migration failing due to memcg limits
@ 2012-07-05  0:44   ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Compaction (and page migration in general) can currently be hindered
through pages being owned by memory cgroups that are at their limits
and unreclaimable.

The reason is that the replacement page is being charged against the
limit while the page being replaced is also still charged.  But this
seems unnecessary, given that only one of the two pages will still be
in use after migration finishes.

This patch changes the memcg migration sequence so that the
replacement page is not charged.  Whatever page is still in use after
successful or failed migration gets to keep the charge of the page
that was going to be replaced.

Reported-by: David Rientjes <rientjes@google.com>
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 include/linux/memcontrol.h |   11 +++----
 mm/memcontrol.c            |   67 +++++++++++++++++++++++--------------------
 mm/migrate.c               |   27 ++++--------------
 3 files changed, 47 insertions(+), 58 deletions(-)

diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 1700762..8444f64 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -100,9 +100,9 @@ int mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *cgroup)
 
 extern struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *memcg);
 
-extern int
-mem_cgroup_prepare_migration(struct page *page,
-	struct page *newpage, struct mem_cgroup **memcgp, gfp_t gfp_mask);
+extern void
+mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
+			     struct mem_cgroup **memcgp);
 extern void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 	struct page *oldpage, struct page *newpage, bool migration_ok);
 
@@ -279,11 +279,10 @@ static inline struct cgroup_subsys_state
 	return NULL;
 }
 
-static inline int
+static inline void
 mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
-	struct mem_cgroup **memcgp, gfp_t gfp_mask)
+			     struct mem_cgroup **memcgp)
 {
-	return 0;
 }
 
 static inline void mem_cgroup_end_migration(struct mem_cgroup *memcg,
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index b11fb2f..4ea19c6 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2909,7 +2909,8 @@ static void mem_cgroup_do_uncharge(struct mem_cgroup *memcg,
  * uncharge if !page_mapped(page)
  */
 static struct mem_cgroup *
-__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
+__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype,
+			     bool end_migration)
 {
 	struct mem_cgroup *memcg = NULL;
 	unsigned int nr_pages = 1;
@@ -2953,7 +2954,16 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
 		/* fallthrough */
 	case MEM_CGROUP_CHARGE_TYPE_DROP:
 		/* See mem_cgroup_prepare_migration() */
-		if (page_mapped(page) || PageCgroupMigration(pc))
+		if (page_mapped(page))
+			goto unlock_out;
+		/*
+		 * Pages under migration may not be uncharged.  But
+		 * end_migration() /must/ be the one uncharging the
+		 * unused post-migration page and so it has to call
+		 * here with the migration bit still set.  See the
+		 * res_counter handling below.
+		 */
+		if (!end_migration && PageCgroupMigration(pc))
 			goto unlock_out;
 		break;
 	case MEM_CGROUP_CHARGE_TYPE_SWAPOUT:
@@ -2987,7 +2997,12 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
 		mem_cgroup_swap_statistics(memcg, true);
 		mem_cgroup_get(memcg);
 	}
-	if (!mem_cgroup_is_root(memcg))
+	/*
+	 * Migration does not charge the res_counter for the
+	 * replacement page, so leave it alone when phasing out the
+	 * page that is unused after the migration.
+	 */
+	if (!end_migration && !mem_cgroup_is_root(memcg))
 		mem_cgroup_do_uncharge(memcg, nr_pages, ctype);
 
 	return memcg;
@@ -3003,14 +3018,14 @@ void mem_cgroup_uncharge_page(struct page *page)
 	if (page_mapped(page))
 		return;
 	VM_BUG_ON(page->mapping && !PageAnon(page));
-	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON);
+	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false);
 }
 
 void mem_cgroup_uncharge_cache_page(struct page *page)
 {
 	VM_BUG_ON(page_mapped(page));
 	VM_BUG_ON(page->mapping);
-	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE);
+	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false);
 }
 
 /*
@@ -3074,7 +3089,7 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
 	if (!swapout) /* this was a swap cache but the swap is unused ! */
 		ctype = MEM_CGROUP_CHARGE_TYPE_DROP;
 
-	memcg = __mem_cgroup_uncharge_common(page, ctype);
+	memcg = __mem_cgroup_uncharge_common(page, ctype, false);
 
 	/*
 	 * record memcg information,  if swapout && memcg != NULL,
@@ -3164,19 +3179,18 @@ static inline int mem_cgroup_move_swap_account(swp_entry_t entry,
  * Before starting migration, account PAGE_SIZE to mem_cgroup that the old
  * page belongs to.
  */
-int mem_cgroup_prepare_migration(struct page *page,
-	struct page *newpage, struct mem_cgroup **memcgp, gfp_t gfp_mask)
+void mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
+				  struct mem_cgroup **memcgp)
 {
 	struct mem_cgroup *memcg = NULL;
 	struct page_cgroup *pc;
 	enum charge_type ctype;
-	int ret = 0;
 
 	*memcgp = NULL;
 
 	VM_BUG_ON(PageTransHuge(page));
 	if (mem_cgroup_disabled())
-		return 0;
+		return;
 
 	pc = lookup_page_cgroup(page);
 	lock_page_cgroup(pc);
@@ -3221,24 +3235,9 @@ int mem_cgroup_prepare_migration(struct page *page,
 	 * we return here.
 	 */
 	if (!memcg)
-		return 0;
+		return;
 
 	*memcgp = memcg;
-	ret = __mem_cgroup_try_charge(NULL, gfp_mask, 1, memcgp, false);
-	css_put(&memcg->css);/* drop extra refcnt */
-	if (ret) {
-		if (PageAnon(page)) {
-			lock_page_cgroup(pc);
-			ClearPageCgroupMigration(pc);
-			unlock_page_cgroup(pc);
-			/*
-			 * The old page may be fully unmapped while we kept it.
-			 */
-			mem_cgroup_uncharge_page(page);
-		}
-		/* we'll need to revisit this error code (we have -EINTR) */
-		return -ENOMEM;
-	}
 	/*
 	 * We charge new page before it's used/mapped. So, even if unlock_page()
 	 * is called before end_migration, we can catch all events on this new
@@ -3251,8 +3250,12 @@ int mem_cgroup_prepare_migration(struct page *page,
 		ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
 	else
 		ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
+	/*
+	 * The page is committed to the memcg, but it's not actually
+	 * charged to the res_counter since we plan on replacing the
+	 * old one and only one page is going to be left afterwards.
+	 */
 	__mem_cgroup_commit_charge(memcg, newpage, 1, ctype, false);
-	return ret;
 }
 
 /* remove redundant charge if migration failed*/
@@ -3274,6 +3277,12 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 		used = newpage;
 		unused = oldpage;
 	}
+	anon = PageAnon(used);
+	__mem_cgroup_uncharge_common(unused,
+		anon ? MEM_CGROUP_CHARGE_TYPE_ANON
+		     : MEM_CGROUP_CHARGE_TYPE_CACHE,
+		true);
+	css_put(&memcg->css);
 	/*
 	 * We disallowed uncharge of pages under migration because mapcount
 	 * of the page goes down to zero, temporarly.
@@ -3283,10 +3292,6 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 	lock_page_cgroup(pc);
 	ClearPageCgroupMigration(pc);
 	unlock_page_cgroup(pc);
-	anon = PageAnon(used);
-	__mem_cgroup_uncharge_common(unused,
-		anon ? MEM_CGROUP_CHARGE_TYPE_ANON
-		     : MEM_CGROUP_CHARGE_TYPE_CACHE);
 
 	/*
 	 * If a page is a file cache, radix-tree replacement is very atomic
diff --git a/mm/migrate.c b/mm/migrate.c
index 8137aea..aa06bf4 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -687,7 +687,6 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
 {
 	int rc = -EAGAIN;
 	int remap_swapcache = 1;
-	int charge = 0;
 	struct mem_cgroup *mem;
 	struct anon_vma *anon_vma = NULL;
 
@@ -729,12 +728,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
 	}
 
 	/* charge against new page */
-	charge = mem_cgroup_prepare_migration(page, newpage, &mem, GFP_KERNEL);
-	if (charge == -ENOMEM) {
-		rc = -ENOMEM;
-		goto unlock;
-	}
-	BUG_ON(charge);
+	mem_cgroup_prepare_migration(page, newpage, &mem);
 
 	if (PageWriteback(page)) {
 		/*
@@ -824,8 +818,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
 		put_anon_vma(anon_vma);
 
 uncharge:
-	if (!charge)
-		mem_cgroup_end_migration(mem, page, newpage, rc == 0);
+	mem_cgroup_end_migration(mem, page, newpage, rc == 0);
 unlock:
 	unlock_page(page);
 out:
@@ -1519,10 +1512,9 @@ migrate_misplaced_page(struct page *page, struct mm_struct *mm, int node)
 {
 	struct page *oldpage = page, *newpage;
 	struct address_space *mapping = page_mapping(page);
-	struct mem_cgroup *mcg;
+	struct mem_cgroup *memcg;
 	unsigned int gfp;
 	int rc = 0;
-	int charge = -ENOMEM;
 
 	VM_BUG_ON(!PageLocked(page));
 	VM_BUG_ON(page_mapcount(page));
@@ -1556,12 +1548,7 @@ migrate_misplaced_page(struct page *page, struct mm_struct *mm, int node)
 	if (!trylock_page(newpage))
 		BUG();		/* new page should be unlocked!!! */
 
-	// XXX hnaz, is this right?
-	charge = mem_cgroup_prepare_migration(page, newpage, &mcg, gfp);
-	if (charge == -ENOMEM) {
-		rc = charge;
-		goto out;
-	}
+	mem_cgroup_prepare_migration(page, newpage, &memcg);
 
 	newpage->index = page->index;
 	newpage->mapping = page->mapping;
@@ -1581,11 +1568,9 @@ migrate_misplaced_page(struct page *page, struct mm_struct *mm, int node)
 		page = newpage;
 	}
 
+	mem_cgroup_end_migration(memcg, oldpage, newpage, !rc);
 out:
-	if (!charge)
-		mem_cgroup_end_migration(mcg, oldpage, newpage, !rc);
-
-       if (oldpage != page)
+	if (oldpage != page)
                put_page(oldpage);
 
 	if (rc) {
-- 
1.7.7.6

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

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 02/11] mm: swapfile: clean up unuse_pte race handling
  2012-07-05  0:44 ` Johannes Weiner
@ 2012-07-05  0:44   ` Johannes Weiner
  -1 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

The conditional mem_cgroup_cancel_charge_swapin() is a leftover from
when the function would continue to reestablish the page even after
mem_cgroup_try_charge_swapin() failed.  After 85d9fc8 "memcg: fix
refcnt handling at swapoff", the condition is always true when this
code is reached.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/swapfile.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/mm/swapfile.c b/mm/swapfile.c
index 64408be..75881ca 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -845,8 +845,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
 
 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	if (unlikely(!pte_same(*pte, swp_entry_to_pte(entry)))) {
-		if (ret > 0)
-			mem_cgroup_cancel_charge_swapin(memcg);
+		mem_cgroup_cancel_charge_swapin(memcg);
 		ret = 0;
 		goto out;
 	}
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 02/11] mm: swapfile: clean up unuse_pte race handling
@ 2012-07-05  0:44   ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

The conditional mem_cgroup_cancel_charge_swapin() is a leftover from
when the function would continue to reestablish the page even after
mem_cgroup_try_charge_swapin() failed.  After 85d9fc8 "memcg: fix
refcnt handling at swapoff", the condition is always true when this
code is reached.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/swapfile.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/mm/swapfile.c b/mm/swapfile.c
index 64408be..75881ca 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -845,8 +845,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
 
 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	if (unlikely(!pte_same(*pte, swp_entry_to_pte(entry)))) {
-		if (ret > 0)
-			mem_cgroup_cancel_charge_swapin(memcg);
+		mem_cgroup_cancel_charge_swapin(memcg);
 		ret = 0;
 		goto out;
 	}
-- 
1.7.7.6

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

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
  2012-07-05  0:44 ` Johannes Weiner
@ 2012-07-05  0:44   ` Johannes Weiner
  -1 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Once charged, swapcache pages can only be uncharged after they are
removed from swapcache again.

Do not try to uncharge pages that are known to be in the swapcache, to
allow future patches to remove checks for that in the uncharge code.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/shmem.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index ee1c5a2..d12b705 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -302,8 +302,6 @@ static int shmem_add_to_page_cache(struct page *page,
 		if (!expected)
 			radix_tree_preload_end();
 	}
-	if (error)
-		mem_cgroup_uncharge_cache_page(page);
 	return error;
 }
 
@@ -1184,11 +1182,14 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
 		__set_page_locked(page);
 		error = mem_cgroup_cache_charge(page, current->mm,
 						gfp & GFP_RECLAIM_MASK);
-		if (!error)
-			error = shmem_add_to_page_cache(page, mapping, index,
-						gfp, NULL);
 		if (error)
 			goto decused;
+		error = shmem_add_to_page_cache(page, mapping, index,
+						gfp, NULL);
+		if (error) {
+			mem_cgroup_uncharge_cache_page(page);
+			goto decused;
+		}
 		lru_cache_add_anon(page);
 
 		spin_lock(&info->lock);
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
@ 2012-07-05  0:44   ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Once charged, swapcache pages can only be uncharged after they are
removed from swapcache again.

Do not try to uncharge pages that are known to be in the swapcache, to
allow future patches to remove checks for that in the uncharge code.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/shmem.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index ee1c5a2..d12b705 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -302,8 +302,6 @@ static int shmem_add_to_page_cache(struct page *page,
 		if (!expected)
 			radix_tree_preload_end();
 	}
-	if (error)
-		mem_cgroup_uncharge_cache_page(page);
 	return error;
 }
 
@@ -1184,11 +1182,14 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
 		__set_page_locked(page);
 		error = mem_cgroup_cache_charge(page, current->mm,
 						gfp & GFP_RECLAIM_MASK);
-		if (!error)
-			error = shmem_add_to_page_cache(page, mapping, index,
-						gfp, NULL);
 		if (error)
 			goto decused;
+		error = shmem_add_to_page_cache(page, mapping, index,
+						gfp, NULL);
+		if (error) {
+			mem_cgroup_uncharge_cache_page(page);
+			goto decused;
+		}
 		lru_cache_add_anon(page);
 
 		spin_lock(&info->lock);
-- 
1.7.7.6

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

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 04/11] mm: memcg: push down PageSwapCache check into uncharge entry functions
  2012-07-05  0:44 ` Johannes Weiner
@ 2012-07-05  0:44   ` Johannes Weiner
  -1 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Not all uncharge paths need to check if the page is swapcache, some of
them can know for sure.

Push down the check into all callsites of uncharge_common() so that
the patch that removes some of them is more obvious.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   18 ++++++++++++------
 1 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 4ea19c6..a3bf414 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2920,8 +2920,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype,
 	if (mem_cgroup_disabled())
 		return NULL;
 
-	if (PageSwapCache(page))
-		return NULL;
+	VM_BUG_ON(PageSwapCache(page));
 
 	if (PageTransHuge(page)) {
 		nr_pages <<= compound_order(page);
@@ -3018,6 +3017,8 @@ void mem_cgroup_uncharge_page(struct page *page)
 	if (page_mapped(page))
 		return;
 	VM_BUG_ON(page->mapping && !PageAnon(page));
+	if (PageSwapCache(page))
+		return;
 	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false);
 }
 
@@ -3025,6 +3026,8 @@ void mem_cgroup_uncharge_cache_page(struct page *page)
 {
 	VM_BUG_ON(page_mapped(page));
 	VM_BUG_ON(page->mapping);
+	if (PageSwapCache(page))
+		return;
 	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false);
 }
 
@@ -3089,6 +3092,8 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
 	if (!swapout) /* this was a swap cache but the swap is unused ! */
 		ctype = MEM_CGROUP_CHARGE_TYPE_DROP;
 
+	if (PageSwapCache(page))
+		return;
 	memcg = __mem_cgroup_uncharge_common(page, ctype, false);
 
 	/*
@@ -3278,10 +3283,11 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 		unused = oldpage;
 	}
 	anon = PageAnon(used);
-	__mem_cgroup_uncharge_common(unused,
-		anon ? MEM_CGROUP_CHARGE_TYPE_ANON
-		     : MEM_CGROUP_CHARGE_TYPE_CACHE,
-		true);
+	if (!PageSwapCache(page))
+		__mem_cgroup_uncharge_common(unused,
+					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
+					     : MEM_CGROUP_CHARGE_TYPE_CACHE,
+					     true);
 	css_put(&memcg->css);
 	/*
 	 * We disallowed uncharge of pages under migration because mapcount
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 04/11] mm: memcg: push down PageSwapCache check into uncharge entry functions
@ 2012-07-05  0:44   ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Not all uncharge paths need to check if the page is swapcache, some of
them can know for sure.

Push down the check into all callsites of uncharge_common() so that
the patch that removes some of them is more obvious.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   18 ++++++++++++------
 1 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 4ea19c6..a3bf414 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2920,8 +2920,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype,
 	if (mem_cgroup_disabled())
 		return NULL;
 
-	if (PageSwapCache(page))
-		return NULL;
+	VM_BUG_ON(PageSwapCache(page));
 
 	if (PageTransHuge(page)) {
 		nr_pages <<= compound_order(page);
@@ -3018,6 +3017,8 @@ void mem_cgroup_uncharge_page(struct page *page)
 	if (page_mapped(page))
 		return;
 	VM_BUG_ON(page->mapping && !PageAnon(page));
+	if (PageSwapCache(page))
+		return;
 	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false);
 }
 
@@ -3025,6 +3026,8 @@ void mem_cgroup_uncharge_cache_page(struct page *page)
 {
 	VM_BUG_ON(page_mapped(page));
 	VM_BUG_ON(page->mapping);
+	if (PageSwapCache(page))
+		return;
 	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false);
 }
 
@@ -3089,6 +3092,8 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
 	if (!swapout) /* this was a swap cache but the swap is unused ! */
 		ctype = MEM_CGROUP_CHARGE_TYPE_DROP;
 
+	if (PageSwapCache(page))
+		return;
 	memcg = __mem_cgroup_uncharge_common(page, ctype, false);
 
 	/*
@@ -3278,10 +3283,11 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 		unused = oldpage;
 	}
 	anon = PageAnon(used);
-	__mem_cgroup_uncharge_common(unused,
-		anon ? MEM_CGROUP_CHARGE_TYPE_ANON
-		     : MEM_CGROUP_CHARGE_TYPE_CACHE,
-		true);
+	if (!PageSwapCache(page))
+		__mem_cgroup_uncharge_common(unused,
+					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
+					     : MEM_CGROUP_CHARGE_TYPE_CACHE,
+					     true);
 	css_put(&memcg->css);
 	/*
 	 * We disallowed uncharge of pages under migration because mapcount
-- 
1.7.7.6

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

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 05/11] mm: memcg: only check for PageSwapCache when uncharging anon
  2012-07-05  0:44 ` Johannes Weiner
@ 2012-07-05  0:44   ` Johannes Weiner
  -1 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Only anon pages that are uncharged at the time of the last page table
mapping vanishing may be in swapcache.

When shmem pages, file pages, swap-freed anon pages, or just migrated
pages are uncharged, they are known for sure to be not in swapcache.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   13 ++++---------
 1 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a3bf414..3d56b4e 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3026,8 +3026,6 @@ void mem_cgroup_uncharge_cache_page(struct page *page)
 {
 	VM_BUG_ON(page_mapped(page));
 	VM_BUG_ON(page->mapping);
-	if (PageSwapCache(page))
-		return;
 	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false);
 }
 
@@ -3092,8 +3090,6 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
 	if (!swapout) /* this was a swap cache but the swap is unused ! */
 		ctype = MEM_CGROUP_CHARGE_TYPE_DROP;
 
-	if (PageSwapCache(page))
-		return;
 	memcg = __mem_cgroup_uncharge_common(page, ctype, false);
 
 	/*
@@ -3283,11 +3279,10 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 		unused = oldpage;
 	}
 	anon = PageAnon(used);
-	if (!PageSwapCache(page))
-		__mem_cgroup_uncharge_common(unused,
-					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
-					     : MEM_CGROUP_CHARGE_TYPE_CACHE,
-					     true);
+	__mem_cgroup_uncharge_common(unused,
+				     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
+				     : MEM_CGROUP_CHARGE_TYPE_CACHE,
+				     true);
 	css_put(&memcg->css);
 	/*
 	 * We disallowed uncharge of pages under migration because mapcount
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 05/11] mm: memcg: only check for PageSwapCache when uncharging anon
@ 2012-07-05  0:44   ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Only anon pages that are uncharged at the time of the last page table
mapping vanishing may be in swapcache.

When shmem pages, file pages, swap-freed anon pages, or just migrated
pages are uncharged, they are known for sure to be not in swapcache.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   13 ++++---------
 1 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a3bf414..3d56b4e 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3026,8 +3026,6 @@ void mem_cgroup_uncharge_cache_page(struct page *page)
 {
 	VM_BUG_ON(page_mapped(page));
 	VM_BUG_ON(page->mapping);
-	if (PageSwapCache(page))
-		return;
 	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false);
 }
 
@@ -3092,8 +3090,6 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
 	if (!swapout) /* this was a swap cache but the swap is unused ! */
 		ctype = MEM_CGROUP_CHARGE_TYPE_DROP;
 
-	if (PageSwapCache(page))
-		return;
 	memcg = __mem_cgroup_uncharge_common(page, ctype, false);
 
 	/*
@@ -3283,11 +3279,10 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 		unused = oldpage;
 	}
 	anon = PageAnon(used);
-	if (!PageSwapCache(page))
-		__mem_cgroup_uncharge_common(unused,
-					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
-					     : MEM_CGROUP_CHARGE_TYPE_CACHE,
-					     true);
+	__mem_cgroup_uncharge_common(unused,
+				     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
+				     : MEM_CGROUP_CHARGE_TYPE_CACHE,
+				     true);
 	css_put(&memcg->css);
 	/*
 	 * We disallowed uncharge of pages under migration because mapcount
-- 
1.7.7.6

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

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 06/11] mm: memcg: move swapin charge functions above callsites
  2012-07-05  0:44 ` Johannes Weiner
@ 2012-07-05  0:44   ` Johannes Weiner
  -1 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Charging cache pages may require swapin in the shmem case.  Save the
forward declaration and just move the swapin functions above the cache
charging functions.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   68 +++++++++++++++++++++++++-----------------------------
 1 files changed, 32 insertions(+), 36 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 3d56b4e..4a41b55 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2729,37 +2729,6 @@ int mem_cgroup_newpage_charge(struct page *page,
 					MEM_CGROUP_CHARGE_TYPE_ANON);
 }
 
-static void
-__mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr,
-					enum charge_type ctype);
-
-int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
-				gfp_t gfp_mask)
-{
-	struct mem_cgroup *memcg = NULL;
-	enum charge_type type = MEM_CGROUP_CHARGE_TYPE_CACHE;
-	int ret;
-
-	if (mem_cgroup_disabled())
-		return 0;
-	if (PageCompound(page))
-		return 0;
-
-	if (unlikely(!mm))
-		mm = &init_mm;
-	if (!page_is_file_cache(page))
-		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
-
-	if (!PageSwapCache(page))
-		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
-	else { /* page is swapcache/shmem */
-		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg);
-		if (!ret)
-			__mem_cgroup_commit_charge_swapin(page, memcg, type);
-	}
-	return ret;
-}
-
 /*
  * While swap-in, try_charge -> commit or cancel, the page is locked.
  * And when try_charge() successfully returns, one refcnt to memcg without
@@ -2806,6 +2775,15 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
 	return ret;
 }
 
+void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg)
+{
+	if (mem_cgroup_disabled())
+		return;
+	if (!memcg)
+		return;
+	__mem_cgroup_cancel_charge(memcg, 1);
+}
+
 static void
 __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *memcg,
 					enum charge_type ctype)
@@ -2843,13 +2821,31 @@ void mem_cgroup_commit_charge_swapin(struct page *page,
 					  MEM_CGROUP_CHARGE_TYPE_ANON);
 }
 
-void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg)
+int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
+				gfp_t gfp_mask)
 {
+	struct mem_cgroup *memcg = NULL;
+	enum charge_type type = MEM_CGROUP_CHARGE_TYPE_CACHE;
+	int ret;
+
 	if (mem_cgroup_disabled())
-		return;
-	if (!memcg)
-		return;
-	__mem_cgroup_cancel_charge(memcg, 1);
+		return 0;
+	if (PageCompound(page))
+		return 0;
+
+	if (unlikely(!mm))
+		mm = &init_mm;
+	if (!page_is_file_cache(page))
+		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
+
+	if (!PageSwapCache(page))
+		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
+	else { /* page is swapcache/shmem */
+		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg);
+		if (!ret)
+			__mem_cgroup_commit_charge_swapin(page, memcg, type);
+	}
+	return ret;
 }
 
 static void mem_cgroup_do_uncharge(struct mem_cgroup *memcg,
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 06/11] mm: memcg: move swapin charge functions above callsites
@ 2012-07-05  0:44   ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Charging cache pages may require swapin in the shmem case.  Save the
forward declaration and just move the swapin functions above the cache
charging functions.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   68 +++++++++++++++++++++++++-----------------------------
 1 files changed, 32 insertions(+), 36 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 3d56b4e..4a41b55 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2729,37 +2729,6 @@ int mem_cgroup_newpage_charge(struct page *page,
 					MEM_CGROUP_CHARGE_TYPE_ANON);
 }
 
-static void
-__mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr,
-					enum charge_type ctype);
-
-int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
-				gfp_t gfp_mask)
-{
-	struct mem_cgroup *memcg = NULL;
-	enum charge_type type = MEM_CGROUP_CHARGE_TYPE_CACHE;
-	int ret;
-
-	if (mem_cgroup_disabled())
-		return 0;
-	if (PageCompound(page))
-		return 0;
-
-	if (unlikely(!mm))
-		mm = &init_mm;
-	if (!page_is_file_cache(page))
-		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
-
-	if (!PageSwapCache(page))
-		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
-	else { /* page is swapcache/shmem */
-		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg);
-		if (!ret)
-			__mem_cgroup_commit_charge_swapin(page, memcg, type);
-	}
-	return ret;
-}
-
 /*
  * While swap-in, try_charge -> commit or cancel, the page is locked.
  * And when try_charge() successfully returns, one refcnt to memcg without
@@ -2806,6 +2775,15 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
 	return ret;
 }
 
+void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg)
+{
+	if (mem_cgroup_disabled())
+		return;
+	if (!memcg)
+		return;
+	__mem_cgroup_cancel_charge(memcg, 1);
+}
+
 static void
 __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *memcg,
 					enum charge_type ctype)
@@ -2843,13 +2821,31 @@ void mem_cgroup_commit_charge_swapin(struct page *page,
 					  MEM_CGROUP_CHARGE_TYPE_ANON);
 }
 
-void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg)
+int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
+				gfp_t gfp_mask)
 {
+	struct mem_cgroup *memcg = NULL;
+	enum charge_type type = MEM_CGROUP_CHARGE_TYPE_CACHE;
+	int ret;
+
 	if (mem_cgroup_disabled())
-		return;
-	if (!memcg)
-		return;
-	__mem_cgroup_cancel_charge(memcg, 1);
+		return 0;
+	if (PageCompound(page))
+		return 0;
+
+	if (unlikely(!mm))
+		mm = &init_mm;
+	if (!page_is_file_cache(page))
+		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
+
+	if (!PageSwapCache(page))
+		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
+	else { /* page is swapcache/shmem */
+		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg);
+		if (!ret)
+			__mem_cgroup_commit_charge_swapin(page, memcg, type);
+	}
+	return ret;
 }
 
 static void mem_cgroup_do_uncharge(struct mem_cgroup *memcg,
-- 
1.7.7.6

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

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 07/11] mm: memcg: remove unneeded shmem charge type
  2012-07-05  0:44 ` Johannes Weiner
@ 2012-07-05  0:44   ` Johannes Weiner
  -1 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

shmem page charges have not needed a separate charge type to tell them
from regular file pages since 08e552c 'memcg: synchronized LRU'.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   11 +----------
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 4a41b55..418b47d 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -379,7 +379,6 @@ static bool move_file(void)
 enum charge_type {
 	MEM_CGROUP_CHARGE_TYPE_CACHE = 0,
 	MEM_CGROUP_CHARGE_TYPE_ANON,
-	MEM_CGROUP_CHARGE_TYPE_SHMEM,	/* used by page migration of shmem */
 	MEM_CGROUP_CHARGE_TYPE_SWAPOUT,	/* for accounting swapcache */
 	MEM_CGROUP_CHARGE_TYPE_DROP,	/* a page was unused swap cache */
 	NR_CHARGE_TYPE,
@@ -2835,8 +2834,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
 
 	if (unlikely(!mm))
 		mm = &init_mm;
-	if (!page_is_file_cache(page))
-		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
 
 	if (!PageSwapCache(page))
 		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
@@ -3243,10 +3240,8 @@ void mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
 	 */
 	if (PageAnon(page))
 		ctype = MEM_CGROUP_CHARGE_TYPE_ANON;
-	else if (page_is_file_cache(page))
-		ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
 	else
-		ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
+		ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
 	/*
 	 * The page is committed to the memcg, but it's not actually
 	 * charged to the res_counter since we plan on replacing the
@@ -3340,10 +3335,6 @@ void mem_cgroup_replace_page_cache(struct page *oldpage,
 	 */
 	if (!memcg)
 		return;
-
-	if (PageSwapBacked(oldpage))
-		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
-
 	/*
 	 * Even if newpage->mapping was NULL before starting replacement,
 	 * the newpage may be on LRU(or pagevec for LRU) already. We lock
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 07/11] mm: memcg: remove unneeded shmem charge type
@ 2012-07-05  0:44   ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

shmem page charges have not needed a separate charge type to tell them
from regular file pages since 08e552c 'memcg: synchronized LRU'.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   11 +----------
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 4a41b55..418b47d 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -379,7 +379,6 @@ static bool move_file(void)
 enum charge_type {
 	MEM_CGROUP_CHARGE_TYPE_CACHE = 0,
 	MEM_CGROUP_CHARGE_TYPE_ANON,
-	MEM_CGROUP_CHARGE_TYPE_SHMEM,	/* used by page migration of shmem */
 	MEM_CGROUP_CHARGE_TYPE_SWAPOUT,	/* for accounting swapcache */
 	MEM_CGROUP_CHARGE_TYPE_DROP,	/* a page was unused swap cache */
 	NR_CHARGE_TYPE,
@@ -2835,8 +2834,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
 
 	if (unlikely(!mm))
 		mm = &init_mm;
-	if (!page_is_file_cache(page))
-		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
 
 	if (!PageSwapCache(page))
 		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
@@ -3243,10 +3240,8 @@ void mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
 	 */
 	if (PageAnon(page))
 		ctype = MEM_CGROUP_CHARGE_TYPE_ANON;
-	else if (page_is_file_cache(page))
-		ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
 	else
-		ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
+		ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
 	/*
 	 * The page is committed to the memcg, but it's not actually
 	 * charged to the res_counter since we plan on replacing the
@@ -3340,10 +3335,6 @@ void mem_cgroup_replace_page_cache(struct page *oldpage,
 	 */
 	if (!memcg)
 		return;
-
-	if (PageSwapBacked(oldpage))
-		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
-
 	/*
 	 * Even if newpage->mapping was NULL before starting replacement,
 	 * the newpage may be on LRU(or pagevec for LRU) already. We lock
-- 
1.7.7.6

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

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
  2012-07-05  0:44 ` Johannes Weiner
@ 2012-07-05  0:45   ` Johannes Weiner
  -1 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:45 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

It does not matter to __mem_cgroup_try_charge() if the passed mm is
NULL or init_mm, it will charge the root memcg in either case.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 418b47d..6fe4101 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2766,8 +2766,6 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
 		ret = 0;
 	return ret;
 charge_cur_mm:
-	if (unlikely(!mm))
-		mm = &init_mm;
 	ret = __mem_cgroup_try_charge(mm, mask, 1, memcgp, true);
 	if (ret == -EINTR)
 		ret = 0;
@@ -2832,9 +2830,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
 	if (PageCompound(page))
 		return 0;
 
-	if (unlikely(!mm))
-		mm = &init_mm;
-
 	if (!PageSwapCache(page))
 		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
 	else { /* page is swapcache/shmem */
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
@ 2012-07-05  0:45   ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:45 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

It does not matter to __mem_cgroup_try_charge() if the passed mm is
NULL or init_mm, it will charge the root memcg in either case.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 418b47d..6fe4101 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2766,8 +2766,6 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
 		ret = 0;
 	return ret;
 charge_cur_mm:
-	if (unlikely(!mm))
-		mm = &init_mm;
 	ret = __mem_cgroup_try_charge(mm, mask, 1, memcgp, true);
 	if (ret == -EINTR)
 		ret = 0;
@@ -2832,9 +2830,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
 	if (PageCompound(page))
 		return 0;
 
-	if (unlikely(!mm))
-		mm = &init_mm;
-
 	if (!PageSwapCache(page))
 		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
 	else { /* page is swapcache/shmem */
-- 
1.7.7.6

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

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 09/11] mm: memcg: split swapin charge function into private and public part
  2012-07-05  0:44 ` Johannes Weiner
@ 2012-07-05  0:45   ` Johannes Weiner
  -1 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:45 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

When shmem is charged upon swapin, it does not need to check twice
whether the memory controller is enabled.

Also, shmem pages do not have to be checked for everything that
regular anon pages have to be checked for, so let shmem use the
internal version directly and allow future patches to move around
checks that are only required when swapping in anon pages.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   24 +++++++++++++++---------
 1 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 6fe4101..a8bf86a 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2734,18 +2734,14 @@ int mem_cgroup_newpage_charge(struct page *page,
  * struct page_cgroup is acquired. This refcnt will be consumed by
  * "commit()" or removed by "cancel()"
  */
-int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
-				 struct page *page,
-				 gfp_t mask, struct mem_cgroup **memcgp)
+static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm,
+					  struct page *page,
+					  gfp_t mask,
+					  struct mem_cgroup **memcgp)
 {
 	struct mem_cgroup *memcg;
 	int ret;
 
-	*memcgp = NULL;
-
-	if (mem_cgroup_disabled())
-		return 0;
-
 	if (!do_swap_account)
 		goto charge_cur_mm;
 	/*
@@ -2772,6 +2768,15 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
 	return ret;
 }
 
+int mem_cgroup_try_charge_swapin(struct mm_struct *mm, struct page *page,
+				 gfp_t gfp_mask, struct mem_cgroup **memcgp)
+{
+	*memcgp = NULL;
+	if (mem_cgroup_disabled())
+		return 0;
+	return __mem_cgroup_try_charge_swapin(mm, page, gfp_mask, memcgp);
+}
+
 void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg)
 {
 	if (mem_cgroup_disabled())
@@ -2833,7 +2838,8 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
 	if (!PageSwapCache(page))
 		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
 	else { /* page is swapcache/shmem */
-		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg);
+		ret = __mem_cgroup_try_charge_swapin(mm, page,
+						     gfp_mask, &memcg);
 		if (!ret)
 			__mem_cgroup_commit_charge_swapin(page, memcg, type);
 	}
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 09/11] mm: memcg: split swapin charge function into private and public part
@ 2012-07-05  0:45   ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:45 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

When shmem is charged upon swapin, it does not need to check twice
whether the memory controller is enabled.

Also, shmem pages do not have to be checked for everything that
regular anon pages have to be checked for, so let shmem use the
internal version directly and allow future patches to move around
checks that are only required when swapping in anon pages.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   24 +++++++++++++++---------
 1 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 6fe4101..a8bf86a 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2734,18 +2734,14 @@ int mem_cgroup_newpage_charge(struct page *page,
  * struct page_cgroup is acquired. This refcnt will be consumed by
  * "commit()" or removed by "cancel()"
  */
-int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
-				 struct page *page,
-				 gfp_t mask, struct mem_cgroup **memcgp)
+static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm,
+					  struct page *page,
+					  gfp_t mask,
+					  struct mem_cgroup **memcgp)
 {
 	struct mem_cgroup *memcg;
 	int ret;
 
-	*memcgp = NULL;
-
-	if (mem_cgroup_disabled())
-		return 0;
-
 	if (!do_swap_account)
 		goto charge_cur_mm;
 	/*
@@ -2772,6 +2768,15 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
 	return ret;
 }
 
+int mem_cgroup_try_charge_swapin(struct mm_struct *mm, struct page *page,
+				 gfp_t gfp_mask, struct mem_cgroup **memcgp)
+{
+	*memcgp = NULL;
+	if (mem_cgroup_disabled())
+		return 0;
+	return __mem_cgroup_try_charge_swapin(mm, page, gfp_mask, memcgp);
+}
+
 void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg)
 {
 	if (mem_cgroup_disabled())
@@ -2833,7 +2838,8 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
 	if (!PageSwapCache(page))
 		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
 	else { /* page is swapcache/shmem */
-		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg);
+		ret = __mem_cgroup_try_charge_swapin(mm, page,
+						     gfp_mask, &memcg);
 		if (!ret)
 			__mem_cgroup_commit_charge_swapin(page, memcg, type);
 	}
-- 
1.7.7.6

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

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 10/11] mm: memcg: only check swap cache pages for repeated charging
  2012-07-05  0:44 ` Johannes Weiner
@ 2012-07-05  0:45   ` Johannes Weiner
  -1 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:45 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Only anon and shmem pages in the swap cache are attempted to be
charged multiple times, from every swap pte fault or from
shmem_unuse().  No other pages require checking PageCgroupUsed().

Charging pages in the swap cache is also serialized by the page lock,
and since both the try_charge and commit_charge are called under the
same page lock section, the PageCgroupUsed() check might as well
happen before the counter charging, let alone reclaim.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   17 ++++++++++++-----
 1 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a8bf86a..d3701cd 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2471,11 +2471,7 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
 	bool anon;
 
 	lock_page_cgroup(pc);
-	if (unlikely(PageCgroupUsed(pc))) {
-		unlock_page_cgroup(pc);
-		__mem_cgroup_cancel_charge(memcg, nr_pages);
-		return;
-	}
+	VM_BUG_ON(PageCgroupUsed(pc));
 	/*
 	 * we don't need page_cgroup_lock about tail pages, becase they are not
 	 * accessed by any other context at this point.
@@ -2740,8 +2736,19 @@ static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm,
 					  struct mem_cgroup **memcgp)
 {
 	struct mem_cgroup *memcg;
+	struct page_cgroup *pc;
 	int ret;
 
+	pc = lookup_page_cgroup(page);
+	/*
+	 * Every swap fault against a single page tries to charge the
+	 * page, bail as early as possible.  shmem_unuse() encounters
+	 * already charged pages, too.  The USED bit is protected by
+	 * the page lock, which serializes swap cache removal, which
+	 * in turn serializes uncharging.
+	 */
+	if (PageCgroupUsed(pc))
+		return 0;
 	if (!do_swap_account)
 		goto charge_cur_mm;
 	/*
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 10/11] mm: memcg: only check swap cache pages for repeated charging
@ 2012-07-05  0:45   ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:45 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

Only anon and shmem pages in the swap cache are attempted to be
charged multiple times, from every swap pte fault or from
shmem_unuse().  No other pages require checking PageCgroupUsed().

Charging pages in the swap cache is also serialized by the page lock,
and since both the try_charge and commit_charge are called under the
same page lock section, the PageCgroupUsed() check might as well
happen before the counter charging, let alone reclaim.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   17 ++++++++++++-----
 1 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a8bf86a..d3701cd 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2471,11 +2471,7 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
 	bool anon;
 
 	lock_page_cgroup(pc);
-	if (unlikely(PageCgroupUsed(pc))) {
-		unlock_page_cgroup(pc);
-		__mem_cgroup_cancel_charge(memcg, nr_pages);
-		return;
-	}
+	VM_BUG_ON(PageCgroupUsed(pc));
 	/*
 	 * we don't need page_cgroup_lock about tail pages, becase they are not
 	 * accessed by any other context at this point.
@@ -2740,8 +2736,19 @@ static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm,
 					  struct mem_cgroup **memcgp)
 {
 	struct mem_cgroup *memcg;
+	struct page_cgroup *pc;
 	int ret;
 
+	pc = lookup_page_cgroup(page);
+	/*
+	 * Every swap fault against a single page tries to charge the
+	 * page, bail as early as possible.  shmem_unuse() encounters
+	 * already charged pages, too.  The USED bit is protected by
+	 * the page lock, which serializes swap cache removal, which
+	 * in turn serializes uncharging.
+	 */
+	if (PageCgroupUsed(pc))
+		return 0;
 	if (!do_swap_account)
 		goto charge_cur_mm;
 	/*
-- 
1.7.7.6

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

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 11/11] mm: memcg: only check anon swapin page charges for swap cache
  2012-07-05  0:44 ` Johannes Weiner
@ 2012-07-05  0:45   ` Johannes Weiner
  -1 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:45 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

shmem knows for sure that the page is in swap cache when attempting to
charge a page, because the cache charge entry function has a check for
it.  Only anon pages may be removed from swap cache already when
trying to charge their swapin.

Adjust the comment, though: '4969c11 mm: fix swapin race condition'
added a stable PageSwapCache check under the page lock in the
do_swap_page() before calling the memory controller, so it's
unuse_pte()'s pte_same() that may fail.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   22 ++++++++++++++--------
 1 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index d3701cd..9b7e256 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2751,14 +2751,6 @@ static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm,
 		return 0;
 	if (!do_swap_account)
 		goto charge_cur_mm;
-	/*
-	 * A racing thread's fault, or swapoff, may have already updated
-	 * the pte, and even removed page from swap cache: in those cases
-	 * do_swap_page()'s pte_same() test will fail; but there's also a
-	 * KSM case which does need to charge the page.
-	 */
-	if (!PageSwapCache(page))
-		goto charge_cur_mm;
 	memcg = try_get_mem_cgroup_from_page(page);
 	if (!memcg)
 		goto charge_cur_mm;
@@ -2781,6 +2773,20 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm, struct page *page,
 	*memcgp = NULL;
 	if (mem_cgroup_disabled())
 		return 0;
+	/*
+	 * A racing thread's fault, or swapoff, may have already
+	 * updated the pte, and even removed page from swap cache: in
+	 * those cases unuse_pte()'s pte_same() test will fail; but
+	 * there's also a KSM case which does need to charge the page.
+	 */
+	if (!PageSwapCache(page)) {
+		int ret;
+
+		ret = __mem_cgroup_try_charge(mm, gfp_mask, 1, memcgp, true);
+		if (ret == -EINTR)
+			ret = 0;
+		return ret;
+	}
 	return __mem_cgroup_try_charge_swapin(mm, page, gfp_mask, memcgp);
 }
 
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [patch 11/11] mm: memcg: only check anon swapin page charges for swap cache
@ 2012-07-05  0:45   ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-05  0:45 UTC (permalink / raw)
  To: Andrew Morton
  Cc: KAMEZAWA Hiroyuki, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

shmem knows for sure that the page is in swap cache when attempting to
charge a page, because the cache charge entry function has a check for
it.  Only anon pages may be removed from swap cache already when
trying to charge their swapin.

Adjust the comment, though: '4969c11 mm: fix swapin race condition'
added a stable PageSwapCache check under the page lock in the
do_swap_page() before calling the memory controller, so it's
unuse_pte()'s pte_same() that may fail.

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/memcontrol.c |   22 ++++++++++++++--------
 1 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index d3701cd..9b7e256 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2751,14 +2751,6 @@ static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm,
 		return 0;
 	if (!do_swap_account)
 		goto charge_cur_mm;
-	/*
-	 * A racing thread's fault, or swapoff, may have already updated
-	 * the pte, and even removed page from swap cache: in those cases
-	 * do_swap_page()'s pte_same() test will fail; but there's also a
-	 * KSM case which does need to charge the page.
-	 */
-	if (!PageSwapCache(page))
-		goto charge_cur_mm;
 	memcg = try_get_mem_cgroup_from_page(page);
 	if (!memcg)
 		goto charge_cur_mm;
@@ -2781,6 +2773,20 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm, struct page *page,
 	*memcgp = NULL;
 	if (mem_cgroup_disabled())
 		return 0;
+	/*
+	 * A racing thread's fault, or swapoff, may have already
+	 * updated the pte, and even removed page from swap cache: in
+	 * those cases unuse_pte()'s pte_same() test will fail; but
+	 * there's also a KSM case which does need to charge the page.
+	 */
+	if (!PageSwapCache(page)) {
+		int ret;
+
+		ret = __mem_cgroup_try_charge(mm, gfp_mask, 1, memcgp, true);
+		if (ret == -EINTR)
+			ret = 0;
+		return ret;
+	}
 	return __mem_cgroup_try_charge_swapin(mm, page, gfp_mask, memcgp);
 }
 
-- 
1.7.7.6

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

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* Re: [patch 01/11] mm: memcg: fix compaction/migration failing due to memcg limits
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09  2:27     ` Kamezawa Hiroyuki
  -1 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:27 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> Compaction (and page migration in general) can currently be hindered
> through pages being owned by memory cgroups that are at their limits
> and unreclaimable.
> 
> The reason is that the replacement page is being charged against the
> limit while the page being replaced is also still charged.  But this
> seems unnecessary, given that only one of the two pages will still be
> in use after migration finishes.
> 
> This patch changes the memcg migration sequence so that the
> replacement page is not charged.  Whatever page is still in use after
> successful or failed migration gets to keep the charge of the page
> that was going to be replaced.
> 
> Reported-by: David Rientjes <rientjes@google.com>
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>


^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 01/11] mm: memcg: fix compaction/migration failing due to memcg limits
@ 2012-07-09  2:27     ` Kamezawa Hiroyuki
  0 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:27 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> Compaction (and page migration in general) can currently be hindered
> through pages being owned by memory cgroups that are at their limits
> and unreclaimable.
> 
> The reason is that the replacement page is being charged against the
> limit while the page being replaced is also still charged.  But this
> seems unnecessary, given that only one of the two pages will still be
> in use after migration finishes.
> 
> This patch changes the memcg migration sequence so that the
> replacement page is not charged.  Whatever page is still in use after
> successful or failed migration gets to keep the charge of the page
> that was going to be replaced.
> 
> Reported-by: David Rientjes <rientjes@google.com>
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 02/11] mm: swapfile: clean up unuse_pte race handling
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09  2:29     ` Kamezawa Hiroyuki
  -1 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:29 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> The conditional mem_cgroup_cancel_charge_swapin() is a leftover from
> when the function would continue to reestablish the page even after
> mem_cgroup_try_charge_swapin() failed.  After 85d9fc8 "memcg: fix
> refcnt handling at swapoff", the condition is always true when this
> code is reached.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>



^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 02/11] mm: swapfile: clean up unuse_pte race handling
@ 2012-07-09  2:29     ` Kamezawa Hiroyuki
  0 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:29 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> The conditional mem_cgroup_cancel_charge_swapin() is a leftover from
> when the function would continue to reestablish the page even after
> mem_cgroup_try_charge_swapin() failed.  After 85d9fc8 "memcg: fix
> refcnt handling at swapoff", the condition is always true when this
> code is reached.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>


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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09  2:33     ` Kamezawa Hiroyuki
  -1 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:33 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> Once charged, swapcache pages can only be uncharged after they are
> removed from swapcache again.
> 
> Do not try to uncharge pages that are known to be in the swapcache, to
> allow future patches to remove checks for that in the uncharge code.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> ---

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>



^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
@ 2012-07-09  2:33     ` Kamezawa Hiroyuki
  0 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:33 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> Once charged, swapcache pages can only be uncharged after they are
> removed from swapcache again.
> 
> Do not try to uncharge pages that are known to be in the swapcache, to
> allow future patches to remove checks for that in the uncharge code.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> ---

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>


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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 04/11] mm: memcg: push down PageSwapCache check into uncharge entry functions
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09  2:42     ` Kamezawa Hiroyuki
  -1 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:42 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> Not all uncharge paths need to check if the page is swapcache, some of
> them can know for sure.
> 
> Push down the check into all callsites of uncharge_common() so that
> the patch that removes some of them is more obvious.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> ---

some nitpick.

>   mm/memcontrol.c |   18 ++++++++++++------
>   1 files changed, 12 insertions(+), 6 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 4ea19c6..a3bf414 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2920,8 +2920,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype,
>   	if (mem_cgroup_disabled())
>   		return NULL;
>   
> -	if (PageSwapCache(page))
> -		return NULL;
> +	VM_BUG_ON(PageSwapCache(page));
>   
>   	if (PageTransHuge(page)) {
>   		nr_pages <<= compound_order(page);
> @@ -3018,6 +3017,8 @@ void mem_cgroup_uncharge_page(struct page *page)
>   	if (page_mapped(page))
>   		return;
>   	VM_BUG_ON(page->mapping && !PageAnon(page));
> +	if (PageSwapCache(page))
> +		return;
>   	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false);
>   }
>   
> @@ -3025,6 +3026,8 @@ void mem_cgroup_uncharge_cache_page(struct page *page)
>   {
>   	VM_BUG_ON(page_mapped(page));
>   	VM_BUG_ON(page->mapping);
> +	if (PageSwapCache(page))
> +		return;
>   	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false);
>   }
>   
> @@ -3089,6 +3092,8 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
>   	if (!swapout) /* this was a swap cache but the swap is unused ! */
>   		ctype = MEM_CGROUP_CHARGE_TYPE_DROP;
>   
> +	if (PageSwapCache(page))
> +		return;
>   	memcg = __mem_cgroup_uncharge_common(page, ctype, false);
>   
>   	/*
> @@ -3278,10 +3283,11 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
>   		unused = oldpage;
>   	}
>   	anon = PageAnon(used);
> -	__mem_cgroup_uncharge_common(unused,
> -		anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> -		     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> -		true);
> +	if (!PageSwapCache(page))
> +		__mem_cgroup_uncharge_common(unused,
> +					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> +					     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> +					     true);

!PageSwapCache(unused) ?

But I think unused page's PG_swapcache is always dropped. So, the check is
not necessary.

Thanks,
-Kame











^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 04/11] mm: memcg: push down PageSwapCache check into uncharge entry functions
@ 2012-07-09  2:42     ` Kamezawa Hiroyuki
  0 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:42 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> Not all uncharge paths need to check if the page is swapcache, some of
> them can know for sure.
> 
> Push down the check into all callsites of uncharge_common() so that
> the patch that removes some of them is more obvious.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> ---

some nitpick.

>   mm/memcontrol.c |   18 ++++++++++++------
>   1 files changed, 12 insertions(+), 6 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 4ea19c6..a3bf414 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2920,8 +2920,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype,
>   	if (mem_cgroup_disabled())
>   		return NULL;
>   
> -	if (PageSwapCache(page))
> -		return NULL;
> +	VM_BUG_ON(PageSwapCache(page));
>   
>   	if (PageTransHuge(page)) {
>   		nr_pages <<= compound_order(page);
> @@ -3018,6 +3017,8 @@ void mem_cgroup_uncharge_page(struct page *page)
>   	if (page_mapped(page))
>   		return;
>   	VM_BUG_ON(page->mapping && !PageAnon(page));
> +	if (PageSwapCache(page))
> +		return;
>   	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false);
>   }
>   
> @@ -3025,6 +3026,8 @@ void mem_cgroup_uncharge_cache_page(struct page *page)
>   {
>   	VM_BUG_ON(page_mapped(page));
>   	VM_BUG_ON(page->mapping);
> +	if (PageSwapCache(page))
> +		return;
>   	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false);
>   }
>   
> @@ -3089,6 +3092,8 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
>   	if (!swapout) /* this was a swap cache but the swap is unused ! */
>   		ctype = MEM_CGROUP_CHARGE_TYPE_DROP;
>   
> +	if (PageSwapCache(page))
> +		return;
>   	memcg = __mem_cgroup_uncharge_common(page, ctype, false);
>   
>   	/*
> @@ -3278,10 +3283,11 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
>   		unused = oldpage;
>   	}
>   	anon = PageAnon(used);
> -	__mem_cgroup_uncharge_common(unused,
> -		anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> -		     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> -		true);
> +	if (!PageSwapCache(page))
> +		__mem_cgroup_uncharge_common(unused,
> +					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> +					     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> +					     true);

!PageSwapCache(unused) ?

But I think unused page's PG_swapcache is always dropped. So, the check is
not necessary.

Thanks,
-Kame










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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 05/11] mm: memcg: only check for PageSwapCache when uncharging anon
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09  2:49     ` Kamezawa Hiroyuki
  -1 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:49 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> Only anon pages that are uncharged at the time of the last page table
> mapping vanishing may be in swapcache.
> 
> When shmem pages, file pages, swap-freed anon pages, or just migrated
> pages are uncharged, they are known for sure to be not in swapcache.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>



^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 05/11] mm: memcg: only check for PageSwapCache when uncharging anon
@ 2012-07-09  2:49     ` Kamezawa Hiroyuki
  0 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:49 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> Only anon pages that are uncharged at the time of the last page table
> mapping vanishing may be in swapcache.
> 
> When shmem pages, file pages, swap-freed anon pages, or just migrated
> pages are uncharged, they are known for sure to be not in swapcache.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>


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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 06/11] mm: memcg: move swapin charge functions above callsites
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09  2:50     ` Kamezawa Hiroyuki
  -1 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:50 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> Charging cache pages may require swapin in the shmem case.  Save the
> forward declaration and just move the swapin functions above the cache
> charging functions.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>



^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 06/11] mm: memcg: move swapin charge functions above callsites
@ 2012-07-09  2:50     ` Kamezawa Hiroyuki
  0 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:50 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> Charging cache pages may require swapin in the shmem case.  Save the
> forward declaration and just move the swapin functions above the cache
> charging functions.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>


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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 07/11] mm: memcg: remove unneeded shmem charge type
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09  2:51     ` Kamezawa Hiroyuki
  -1 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:51 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> shmem page charges have not needed a separate charge type to tell them
> from regular file pages since 08e552c 'memcg: synchronized LRU'.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>



^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 07/11] mm: memcg: remove unneeded shmem charge type
@ 2012-07-09  2:51     ` Kamezawa Hiroyuki
  0 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:51 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:44), Johannes Weiner wrote:
> shmem page charges have not needed a separate charge type to tell them
> from regular file pages since 08e552c 'memcg: synchronized LRU'.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>


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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
  2012-07-05  0:45   ` Johannes Weiner
@ 2012-07-09  2:53     ` Kamezawa Hiroyuki
  -1 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:53 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:45), Johannes Weiner wrote:
> It does not matter to __mem_cgroup_try_charge() if the passed mm is
> NULL or init_mm, it will charge the root memcg in either case.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>



^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
@ 2012-07-09  2:53     ` Kamezawa Hiroyuki
  0 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:53 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:45), Johannes Weiner wrote:
> It does not matter to __mem_cgroup_try_charge() if the passed mm is
> NULL or init_mm, it will charge the root memcg in either case.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>


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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 09/11] mm: memcg: split swapin charge function into private and public part
  2012-07-05  0:45   ` Johannes Weiner
@ 2012-07-09  2:55     ` Kamezawa Hiroyuki
  -1 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:55 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:45), Johannes Weiner wrote:
> When shmem is charged upon swapin, it does not need to check twice
> whether the memory controller is enabled.
> 
> Also, shmem pages do not have to be checked for everything that
> regular anon pages have to be checked for, so let shmem use the
> internal version directly and allow future patches to move around
> checks that are only required when swapping in anon pages.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>



^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 09/11] mm: memcg: split swapin charge function into private and public part
@ 2012-07-09  2:55     ` Kamezawa Hiroyuki
  0 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  2:55 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:45), Johannes Weiner wrote:
> When shmem is charged upon swapin, it does not need to check twice
> whether the memory controller is enabled.
> 
> Also, shmem pages do not have to be checked for everything that
> regular anon pages have to be checked for, so let shmem use the
> internal version directly and allow future patches to move around
> checks that are only required when swapping in anon pages.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>


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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 10/11] mm: memcg: only check swap cache pages for repeated charging
  2012-07-05  0:45   ` Johannes Weiner
@ 2012-07-09  3:26     ` Kamezawa Hiroyuki
  -1 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  3:26 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:45), Johannes Weiner wrote:
> Only anon and shmem pages in the swap cache are attempted to be
> charged multiple times, from every swap pte fault or from
> shmem_unuse().  No other pages require checking PageCgroupUsed().
> 
> Charging pages in the swap cache is also serialized by the page lock,
> and since both the try_charge and commit_charge are called under the
> same page lock section, the PageCgroupUsed() check might as well
> happen before the counter charging, let alone reclaim.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

You're right. This is SwapCache handling is done by commit d13d144309d...
I should notice this....

Thank you very much !

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>


^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 10/11] mm: memcg: only check swap cache pages for repeated charging
@ 2012-07-09  3:26     ` Kamezawa Hiroyuki
  0 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  3:26 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:45), Johannes Weiner wrote:
> Only anon and shmem pages in the swap cache are attempted to be
> charged multiple times, from every swap pte fault or from
> shmem_unuse().  No other pages require checking PageCgroupUsed().
> 
> Charging pages in the swap cache is also serialized by the page lock,
> and since both the try_charge and commit_charge are called under the
> same page lock section, the PageCgroupUsed() check might as well
> happen before the counter charging, let alone reclaim.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

You're right. This is SwapCache handling is done by commit d13d144309d...
I should notice this....

Thank you very much !

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 11/11] mm: memcg: only check anon swapin page charges for swap cache
  2012-07-05  0:45   ` Johannes Weiner
@ 2012-07-09  3:44     ` Kamezawa Hiroyuki
  -1 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  3:44 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:45), Johannes Weiner wrote:
> shmem knows for sure that the page is in swap cache when attempting to
> charge a page, because the cache charge entry function has a check for
> it.  Only anon pages may be removed from swap cache already when
> trying to charge their swapin.
> 
> Adjust the comment, though: '4969c11 mm: fix swapin race condition'
> added a stable PageSwapCache check under the page lock in the
> do_swap_page() before calling the memory controller, so it's
> unuse_pte()'s pte_same() that may fail.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>



^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 11/11] mm: memcg: only check anon swapin page charges for swap cache
@ 2012-07-09  3:44     ` Kamezawa Hiroyuki
  0 siblings, 0 replies; 90+ messages in thread
From: Kamezawa Hiroyuki @ 2012-07-09  3:44 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

(2012/07/05 9:45), Johannes Weiner wrote:
> shmem knows for sure that the page is in swap cache when attempting to
> charge a page, because the cache charge entry function has a check for
> it.  Only anon pages may be removed from swap cache already when
> trying to charge their swapin.
> 
> Adjust the comment, though: '4969c11 mm: fix swapin race condition'
> added a stable PageSwapCache check under the page lock in the
> do_swap_page() before calling the memory controller, so it's
> unuse_pte()'s pte_same() that may fail.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>


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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 04/11] mm: memcg: push down PageSwapCache check into uncharge entry functions
  2012-07-09  2:42     ` Kamezawa Hiroyuki
@ 2012-07-09  7:36       ` Johannes Weiner
  -1 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-09  7:36 UTC (permalink / raw)
  To: Kamezawa Hiroyuki
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Mon, Jul 09, 2012 at 11:42:12AM +0900, Kamezawa Hiroyuki wrote:
> (2012/07/05 9:44), Johannes Weiner wrote:
> > @@ -3278,10 +3283,11 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
> >   		unused = oldpage;
> >   	}
> >   	anon = PageAnon(used);
> > -	__mem_cgroup_uncharge_common(unused,
> > -		anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> > -		     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> > -		true);
> > +	if (!PageSwapCache(page))
> > +		__mem_cgroup_uncharge_common(unused,
> > +					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> > +					     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> > +					     true);
> 
> !PageSwapCache(unused) ?

Argh, right.

> But I think unused page's PG_swapcache is always dropped. So, the check is
> not necessary.

Oh, this is intentional: the check was in __mem_cgroup_uncharge_common
before, which means it applied to this entry point as well.  This is
supposed to be a mechanical change that does not change any logic.
The check is then removed in the next patch.

---
Subject: mm: memcg: push down PageSwapCache check into uncharge entry functions fix

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a3bf414..f4ff18a 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3283,7 +3283,7 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 		unused = oldpage;
 	}
 	anon = PageAnon(used);
-	if (!PageSwapCache(page))
+	if (!PageSwapCache(unused))
 		__mem_cgroup_uncharge_common(unused,
 					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
 					     : MEM_CGROUP_CHARGE_TYPE_CACHE,


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* Re: [patch 04/11] mm: memcg: push down PageSwapCache check into uncharge entry functions
@ 2012-07-09  7:36       ` Johannes Weiner
  0 siblings, 0 replies; 90+ messages in thread
From: Johannes Weiner @ 2012-07-09  7:36 UTC (permalink / raw)
  To: Kamezawa Hiroyuki
  Cc: Andrew Morton, Michal Hocko, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Mon, Jul 09, 2012 at 11:42:12AM +0900, Kamezawa Hiroyuki wrote:
> (2012/07/05 9:44), Johannes Weiner wrote:
> > @@ -3278,10 +3283,11 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
> >   		unused = oldpage;
> >   	}
> >   	anon = PageAnon(used);
> > -	__mem_cgroup_uncharge_common(unused,
> > -		anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> > -		     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> > -		true);
> > +	if (!PageSwapCache(page))
> > +		__mem_cgroup_uncharge_common(unused,
> > +					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> > +					     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> > +					     true);
> 
> !PageSwapCache(unused) ?

Argh, right.

> But I think unused page's PG_swapcache is always dropped. So, the check is
> not necessary.

Oh, this is intentional: the check was in __mem_cgroup_uncharge_common
before, which means it applied to this entry point as well.  This is
supposed to be a mechanical change that does not change any logic.
The check is then removed in the next patch.

---
Subject: mm: memcg: push down PageSwapCache check into uncharge entry functions fix

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a3bf414..f4ff18a 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3283,7 +3283,7 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 		unused = oldpage;
 	}
 	anon = PageAnon(used);
-	if (!PageSwapCache(page))
+	if (!PageSwapCache(unused))
 		__mem_cgroup_uncharge_common(unused,
 					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
 					     : MEM_CGROUP_CHARGE_TYPE_CACHE,

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

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* Re: [patch 01/11] mm: memcg: fix compaction/migration failing due to memcg limits
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09 14:15     ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 14:15 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel, Ingo Molnar

[CCing Ingo for the memcg-devel vs tip/sched/numa inter tree dependency
 - see bellow]

On Thu 05-07-12 02:44:53, Johannes Weiner wrote:
> Compaction (and page migration in general) can currently be hindered
> through pages being owned by memory cgroups that are at their limits
> and unreclaimable.
> 
> The reason is that the replacement page is being charged against the
> limit while the page being replaced is also still charged.  But this
> seems unnecessary, given that only one of the two pages will still be
> in use after migration finishes.
> 
> This patch changes the memcg migration sequence so that the
> replacement page is not charged.  Whatever page is still in use after
> successful or failed migration gets to keep the charge of the page
> that was going to be replaced.

Could you mention the side effect on the stat vs charges discrepancy,
please?

> Reported-by: David Rientjes <rientjes@google.com>
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: Michal Hocko <mhocko@suse.cz>

[...]
> diff --git a/mm/migrate.c b/mm/migrate.c
> index 8137aea..aa06bf4 100644
> --- a/mm/migrate.c
> +++ b/mm/migrate.c
[...]
> @@ -1519,10 +1512,9 @@ migrate_misplaced_page(struct page *page, struct mm_struct *mm, int node)
>  {
>  	struct page *oldpage = page, *newpage;
>  	struct address_space *mapping = page_mapping(page);
> -	struct mem_cgroup *mcg;
> +	struct mem_cgroup *memcg;
>  	unsigned int gfp;
>  	int rc = 0;
> -	int charge = -ENOMEM;
>  
>  	VM_BUG_ON(!PageLocked(page));
>  	VM_BUG_ON(page_mapcount(page));
> @@ -1556,12 +1548,7 @@ migrate_misplaced_page(struct page *page, struct mm_struct *mm, int node)
>  	if (!trylock_page(newpage))
>  		BUG();		/* new page should be unlocked!!! */
>  
> -	// XXX hnaz, is this right?
> -	charge = mem_cgroup_prepare_migration(page, newpage, &mcg, gfp);
> -	if (charge == -ENOMEM) {
> -		rc = charge;
> -		goto out;
> -	}
> +	mem_cgroup_prepare_migration(page, newpage, &memcg);
>  
>  	newpage->index = page->index;
>  	newpage->mapping = page->mapping;
> @@ -1581,11 +1568,9 @@ migrate_misplaced_page(struct page *page, struct mm_struct *mm, int node)
>  		page = newpage;
>  	}
>  
> +	mem_cgroup_end_migration(memcg, oldpage, newpage, !rc);
>  out:
> -	if (!charge)
> -		mem_cgroup_end_migration(mcg, oldpage, newpage, !rc);
> -
> -       if (oldpage != page)
> +	if (oldpage != page)
>                 put_page(oldpage);
>  
>  	if (rc) {

Hmm, this depends on 4783af47 (mm: Migrate misplaced page) from
tip/sched/numa which adds an inter tree dependency which is quite
unfortunate from memcg-devel (aka mmotm git tree) tree POV. 
I can cherry-pick this patch into memcg-devel but I am not sure what
is the merging status of the patch (XXX sounds like it is going to be
updated later). Ingo?

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 01/11] mm: memcg: fix compaction/migration failing due to memcg limits
@ 2012-07-09 14:15     ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 14:15 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel, Ingo Molnar

[CCing Ingo for the memcg-devel vs tip/sched/numa inter tree dependency
 - see bellow]

On Thu 05-07-12 02:44:53, Johannes Weiner wrote:
> Compaction (and page migration in general) can currently be hindered
> through pages being owned by memory cgroups that are at their limits
> and unreclaimable.
> 
> The reason is that the replacement page is being charged against the
> limit while the page being replaced is also still charged.  But this
> seems unnecessary, given that only one of the two pages will still be
> in use after migration finishes.
> 
> This patch changes the memcg migration sequence so that the
> replacement page is not charged.  Whatever page is still in use after
> successful or failed migration gets to keep the charge of the page
> that was going to be replaced.

Could you mention the side effect on the stat vs charges discrepancy,
please?

> Reported-by: David Rientjes <rientjes@google.com>
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: Michal Hocko <mhocko@suse.cz>

[...]
> diff --git a/mm/migrate.c b/mm/migrate.c
> index 8137aea..aa06bf4 100644
> --- a/mm/migrate.c
> +++ b/mm/migrate.c
[...]
> @@ -1519,10 +1512,9 @@ migrate_misplaced_page(struct page *page, struct mm_struct *mm, int node)
>  {
>  	struct page *oldpage = page, *newpage;
>  	struct address_space *mapping = page_mapping(page);
> -	struct mem_cgroup *mcg;
> +	struct mem_cgroup *memcg;
>  	unsigned int gfp;
>  	int rc = 0;
> -	int charge = -ENOMEM;
>  
>  	VM_BUG_ON(!PageLocked(page));
>  	VM_BUG_ON(page_mapcount(page));
> @@ -1556,12 +1548,7 @@ migrate_misplaced_page(struct page *page, struct mm_struct *mm, int node)
>  	if (!trylock_page(newpage))
>  		BUG();		/* new page should be unlocked!!! */
>  
> -	// XXX hnaz, is this right?
> -	charge = mem_cgroup_prepare_migration(page, newpage, &mcg, gfp);
> -	if (charge == -ENOMEM) {
> -		rc = charge;
> -		goto out;
> -	}
> +	mem_cgroup_prepare_migration(page, newpage, &memcg);
>  
>  	newpage->index = page->index;
>  	newpage->mapping = page->mapping;
> @@ -1581,11 +1568,9 @@ migrate_misplaced_page(struct page *page, struct mm_struct *mm, int node)
>  		page = newpage;
>  	}
>  
> +	mem_cgroup_end_migration(memcg, oldpage, newpage, !rc);
>  out:
> -	if (!charge)
> -		mem_cgroup_end_migration(mcg, oldpage, newpage, !rc);
> -
> -       if (oldpage != page)
> +	if (oldpage != page)
>                 put_page(oldpage);
>  
>  	if (rc) {

Hmm, this depends on 4783af47 (mm: Migrate misplaced page) from
tip/sched/numa which adds an inter tree dependency which is quite
unfortunate from memcg-devel (aka mmotm git tree) tree POV. 
I can cherry-pick this patch into memcg-devel but I am not sure what
is the merging status of the patch (XXX sounds like it is going to be
updated later). Ingo?

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 02/11] mm: swapfile: clean up unuse_pte race handling
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09 14:22     ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 14:22 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:54, Johannes Weiner wrote:
> The conditional mem_cgroup_cancel_charge_swapin() is a leftover from
> when the function would continue to reestablish the page even after
> mem_cgroup_try_charge_swapin() failed.  After 85d9fc8 "memcg: fix
> refcnt handling at swapoff", the condition is always true when this
> code is reached.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/swapfile.c |    3 +--
>  1 files changed, 1 insertions(+), 2 deletions(-)
> 
> diff --git a/mm/swapfile.c b/mm/swapfile.c
> index 64408be..75881ca 100644
> --- a/mm/swapfile.c
> +++ b/mm/swapfile.c
> @@ -845,8 +845,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
>  
>  	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
>  	if (unlikely(!pte_same(*pte, swp_entry_to_pte(entry)))) {
> -		if (ret > 0)
> -			mem_cgroup_cancel_charge_swapin(memcg);
> +		mem_cgroup_cancel_charge_swapin(memcg);
>  		ret = 0;
>  		goto out;
>  	}
> -- 
> 1.7.7.6
> 

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 02/11] mm: swapfile: clean up unuse_pte race handling
@ 2012-07-09 14:22     ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 14:22 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:54, Johannes Weiner wrote:
> The conditional mem_cgroup_cancel_charge_swapin() is a leftover from
> when the function would continue to reestablish the page even after
> mem_cgroup_try_charge_swapin() failed.  After 85d9fc8 "memcg: fix
> refcnt handling at swapoff", the condition is always true when this
> code is reached.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/swapfile.c |    3 +--
>  1 files changed, 1 insertions(+), 2 deletions(-)
> 
> diff --git a/mm/swapfile.c b/mm/swapfile.c
> index 64408be..75881ca 100644
> --- a/mm/swapfile.c
> +++ b/mm/swapfile.c
> @@ -845,8 +845,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
>  
>  	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
>  	if (unlikely(!pte_same(*pte, swp_entry_to_pte(entry)))) {
> -		if (ret > 0)
> -			mem_cgroup_cancel_charge_swapin(memcg);
> +		mem_cgroup_cancel_charge_swapin(memcg);
>  		ret = 0;
>  		goto out;
>  	}
> -- 
> 1.7.7.6
> 

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09 14:46     ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 14:46 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:55, Johannes Weiner wrote:
> Once charged, swapcache pages can only be uncharged after they are
> removed from swapcache again.
> 
> Do not try to uncharge pages that are known to be in the swapcache, to
> allow future patches to remove checks for that in the uncharge code.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> ---
>  mm/shmem.c |   11 ++++++-----
>  1 files changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/mm/shmem.c b/mm/shmem.c
> index ee1c5a2..d12b705 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -302,8 +302,6 @@ static int shmem_add_to_page_cache(struct page *page,
>  		if (!expected)
>  			radix_tree_preload_end();
>  	}
> -	if (error)
> -		mem_cgroup_uncharge_cache_page(page);

Maybe I am missing something but who does the uncharge from:
shmem_unuse
  mem_cgroup_cache_charge
  shmem_unuse_inode
    shmem_add_to_page_cache

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
@ 2012-07-09 14:46     ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 14:46 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:55, Johannes Weiner wrote:
> Once charged, swapcache pages can only be uncharged after they are
> removed from swapcache again.
> 
> Do not try to uncharge pages that are known to be in the swapcache, to
> allow future patches to remove checks for that in the uncharge code.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> ---
>  mm/shmem.c |   11 ++++++-----
>  1 files changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/mm/shmem.c b/mm/shmem.c
> index ee1c5a2..d12b705 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -302,8 +302,6 @@ static int shmem_add_to_page_cache(struct page *page,
>  		if (!expected)
>  			radix_tree_preload_end();
>  	}
> -	if (error)
> -		mem_cgroup_uncharge_cache_page(page);

Maybe I am missing something but who does the uncharge from:
shmem_unuse
  mem_cgroup_cache_charge
  shmem_unuse_inode
    shmem_add_to_page_cache

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 04/11] mm: memcg: push down PageSwapCache check into uncharge entry functions
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09 15:02     ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:02 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:56, Johannes Weiner wrote:
> Not all uncharge paths need to check if the page is swapcache, some of
> them can know for sure.
> 
> Push down the check into all callsites of uncharge_common() so that
> the patch that removes some of them is more obvious.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

with the fix later in the thread
Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   18 ++++++++++++------
>  1 files changed, 12 insertions(+), 6 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 4ea19c6..a3bf414 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2920,8 +2920,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype,
>  	if (mem_cgroup_disabled())
>  		return NULL;
>  
> -	if (PageSwapCache(page))
> -		return NULL;
> +	VM_BUG_ON(PageSwapCache(page));
>  
>  	if (PageTransHuge(page)) {
>  		nr_pages <<= compound_order(page);
> @@ -3018,6 +3017,8 @@ void mem_cgroup_uncharge_page(struct page *page)
>  	if (page_mapped(page))
>  		return;
>  	VM_BUG_ON(page->mapping && !PageAnon(page));
> +	if (PageSwapCache(page))
> +		return;
>  	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false);
>  }
>  
> @@ -3025,6 +3026,8 @@ void mem_cgroup_uncharge_cache_page(struct page *page)
>  {
>  	VM_BUG_ON(page_mapped(page));
>  	VM_BUG_ON(page->mapping);
> +	if (PageSwapCache(page))
> +		return;
>  	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false);
>  }
>  
> @@ -3089,6 +3092,8 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
>  	if (!swapout) /* this was a swap cache but the swap is unused ! */
>  		ctype = MEM_CGROUP_CHARGE_TYPE_DROP;
>  
> +	if (PageSwapCache(page))
> +		return;
>  	memcg = __mem_cgroup_uncharge_common(page, ctype, false);
>  
>  	/*
> @@ -3278,10 +3283,11 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
>  		unused = oldpage;
>  	}
>  	anon = PageAnon(used);
> -	__mem_cgroup_uncharge_common(unused,
> -		anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> -		     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> -		true);
> +	if (!PageSwapCache(page))
> +		__mem_cgroup_uncharge_common(unused,
> +					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> +					     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> +					     true);
>  	css_put(&memcg->css);
>  	/*
>  	 * We disallowed uncharge of pages under migration because mapcount
> -- 
> 1.7.7.6
> 

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 04/11] mm: memcg: push down PageSwapCache check into uncharge entry functions
@ 2012-07-09 15:02     ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:02 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:56, Johannes Weiner wrote:
> Not all uncharge paths need to check if the page is swapcache, some of
> them can know for sure.
> 
> Push down the check into all callsites of uncharge_common() so that
> the patch that removes some of them is more obvious.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

with the fix later in the thread
Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   18 ++++++++++++------
>  1 files changed, 12 insertions(+), 6 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 4ea19c6..a3bf414 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2920,8 +2920,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype,
>  	if (mem_cgroup_disabled())
>  		return NULL;
>  
> -	if (PageSwapCache(page))
> -		return NULL;
> +	VM_BUG_ON(PageSwapCache(page));
>  
>  	if (PageTransHuge(page)) {
>  		nr_pages <<= compound_order(page);
> @@ -3018,6 +3017,8 @@ void mem_cgroup_uncharge_page(struct page *page)
>  	if (page_mapped(page))
>  		return;
>  	VM_BUG_ON(page->mapping && !PageAnon(page));
> +	if (PageSwapCache(page))
> +		return;
>  	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false);
>  }
>  
> @@ -3025,6 +3026,8 @@ void mem_cgroup_uncharge_cache_page(struct page *page)
>  {
>  	VM_BUG_ON(page_mapped(page));
>  	VM_BUG_ON(page->mapping);
> +	if (PageSwapCache(page))
> +		return;
>  	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false);
>  }
>  
> @@ -3089,6 +3092,8 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
>  	if (!swapout) /* this was a swap cache but the swap is unused ! */
>  		ctype = MEM_CGROUP_CHARGE_TYPE_DROP;
>  
> +	if (PageSwapCache(page))
> +		return;
>  	memcg = __mem_cgroup_uncharge_common(page, ctype, false);
>  
>  	/*
> @@ -3278,10 +3283,11 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
>  		unused = oldpage;
>  	}
>  	anon = PageAnon(used);
> -	__mem_cgroup_uncharge_common(unused,
> -		anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> -		     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> -		true);
> +	if (!PageSwapCache(page))
> +		__mem_cgroup_uncharge_common(unused,
> +					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> +					     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> +					     true);
>  	css_put(&memcg->css);
>  	/*
>  	 * We disallowed uncharge of pages under migration because mapcount
> -- 
> 1.7.7.6
> 

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 05/11] mm: memcg: only check for PageSwapCache when uncharging anon
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09 15:05     ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:05 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:57, Johannes Weiner wrote:
> Only anon pages that are uncharged at the time of the last page table
> mapping vanishing may be in swapcache.
> 
> When shmem pages, file pages, swap-freed anon pages, or just migrated
> pages are uncharged, they are known for sure to be not in swapcache.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   13 ++++---------
>  1 files changed, 4 insertions(+), 9 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index a3bf414..3d56b4e 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -3026,8 +3026,6 @@ void mem_cgroup_uncharge_cache_page(struct page *page)
>  {
>  	VM_BUG_ON(page_mapped(page));
>  	VM_BUG_ON(page->mapping);
> -	if (PageSwapCache(page))
> -		return;
>  	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false);
>  }
>  
> @@ -3092,8 +3090,6 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
>  	if (!swapout) /* this was a swap cache but the swap is unused ! */
>  		ctype = MEM_CGROUP_CHARGE_TYPE_DROP;
>  
> -	if (PageSwapCache(page))
> -		return;
>  	memcg = __mem_cgroup_uncharge_common(page, ctype, false);
>  
>  	/*
> @@ -3283,11 +3279,10 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
>  		unused = oldpage;
>  	}
>  	anon = PageAnon(used);
> -	if (!PageSwapCache(page))
> -		__mem_cgroup_uncharge_common(unused,
> -					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> -					     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> -					     true);
> +	__mem_cgroup_uncharge_common(unused,
> +				     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> +				     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> +				     true);
>  	css_put(&memcg->css);
>  	/*
>  	 * We disallowed uncharge of pages under migration because mapcount
> -- 
> 1.7.7.6
> 

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 05/11] mm: memcg: only check for PageSwapCache when uncharging anon
@ 2012-07-09 15:05     ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:05 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:57, Johannes Weiner wrote:
> Only anon pages that are uncharged at the time of the last page table
> mapping vanishing may be in swapcache.
> 
> When shmem pages, file pages, swap-freed anon pages, or just migrated
> pages are uncharged, they are known for sure to be not in swapcache.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   13 ++++---------
>  1 files changed, 4 insertions(+), 9 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index a3bf414..3d56b4e 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -3026,8 +3026,6 @@ void mem_cgroup_uncharge_cache_page(struct page *page)
>  {
>  	VM_BUG_ON(page_mapped(page));
>  	VM_BUG_ON(page->mapping);
> -	if (PageSwapCache(page))
> -		return;
>  	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false);
>  }
>  
> @@ -3092,8 +3090,6 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
>  	if (!swapout) /* this was a swap cache but the swap is unused ! */
>  		ctype = MEM_CGROUP_CHARGE_TYPE_DROP;
>  
> -	if (PageSwapCache(page))
> -		return;
>  	memcg = __mem_cgroup_uncharge_common(page, ctype, false);
>  
>  	/*
> @@ -3283,11 +3279,10 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
>  		unused = oldpage;
>  	}
>  	anon = PageAnon(used);
> -	if (!PageSwapCache(page))
> -		__mem_cgroup_uncharge_common(unused,
> -					     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> -					     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> -					     true);
> +	__mem_cgroup_uncharge_common(unused,
> +				     anon ? MEM_CGROUP_CHARGE_TYPE_ANON
> +				     : MEM_CGROUP_CHARGE_TYPE_CACHE,
> +				     true);
>  	css_put(&memcg->css);
>  	/*
>  	 * We disallowed uncharge of pages under migration because mapcount
> -- 
> 1.7.7.6
> 

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 06/11] mm: memcg: move swapin charge functions above callsites
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09 15:10     ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:10 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:58, Johannes Weiner wrote:
> Charging cache pages may require swapin in the shmem case.  Save the
> forward declaration and just move the swapin functions above the cache
> charging functions.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

OK
Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   68 +++++++++++++++++++++++++-----------------------------
>  1 files changed, 32 insertions(+), 36 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 3d56b4e..4a41b55 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2729,37 +2729,6 @@ int mem_cgroup_newpage_charge(struct page *page,
>  					MEM_CGROUP_CHARGE_TYPE_ANON);
>  }
>  
> -static void
> -__mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr,
> -					enum charge_type ctype);
> -
> -int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
> -				gfp_t gfp_mask)
> -{
> -	struct mem_cgroup *memcg = NULL;
> -	enum charge_type type = MEM_CGROUP_CHARGE_TYPE_CACHE;
> -	int ret;
> -
> -	if (mem_cgroup_disabled())
> -		return 0;
> -	if (PageCompound(page))
> -		return 0;
> -
> -	if (unlikely(!mm))
> -		mm = &init_mm;
> -	if (!page_is_file_cache(page))
> -		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
> -
> -	if (!PageSwapCache(page))
> -		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
> -	else { /* page is swapcache/shmem */
> -		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg);
> -		if (!ret)
> -			__mem_cgroup_commit_charge_swapin(page, memcg, type);
> -	}
> -	return ret;
> -}
> -
>  /*
>   * While swap-in, try_charge -> commit or cancel, the page is locked.
>   * And when try_charge() successfully returns, one refcnt to memcg without
> @@ -2806,6 +2775,15 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>  	return ret;
>  }
>  
> +void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg)
> +{
> +	if (mem_cgroup_disabled())
> +		return;
> +	if (!memcg)
> +		return;
> +	__mem_cgroup_cancel_charge(memcg, 1);
> +}
> +
>  static void
>  __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *memcg,
>  					enum charge_type ctype)
> @@ -2843,13 +2821,31 @@ void mem_cgroup_commit_charge_swapin(struct page *page,
>  					  MEM_CGROUP_CHARGE_TYPE_ANON);
>  }
>  
> -void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg)
> +int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
> +				gfp_t gfp_mask)
>  {
> +	struct mem_cgroup *memcg = NULL;
> +	enum charge_type type = MEM_CGROUP_CHARGE_TYPE_CACHE;
> +	int ret;
> +
>  	if (mem_cgroup_disabled())
> -		return;
> -	if (!memcg)
> -		return;
> -	__mem_cgroup_cancel_charge(memcg, 1);
> +		return 0;
> +	if (PageCompound(page))
> +		return 0;
> +
> +	if (unlikely(!mm))
> +		mm = &init_mm;
> +	if (!page_is_file_cache(page))
> +		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
> +
> +	if (!PageSwapCache(page))
> +		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
> +	else { /* page is swapcache/shmem */
> +		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg);
> +		if (!ret)
> +			__mem_cgroup_commit_charge_swapin(page, memcg, type);
> +	}
> +	return ret;
>  }
>  
>  static void mem_cgroup_do_uncharge(struct mem_cgroup *memcg,
> -- 
> 1.7.7.6
> 

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 06/11] mm: memcg: move swapin charge functions above callsites
@ 2012-07-09 15:10     ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:10 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:58, Johannes Weiner wrote:
> Charging cache pages may require swapin in the shmem case.  Save the
> forward declaration and just move the swapin functions above the cache
> charging functions.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

OK
Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   68 +++++++++++++++++++++++++-----------------------------
>  1 files changed, 32 insertions(+), 36 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 3d56b4e..4a41b55 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2729,37 +2729,6 @@ int mem_cgroup_newpage_charge(struct page *page,
>  					MEM_CGROUP_CHARGE_TYPE_ANON);
>  }
>  
> -static void
> -__mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr,
> -					enum charge_type ctype);
> -
> -int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
> -				gfp_t gfp_mask)
> -{
> -	struct mem_cgroup *memcg = NULL;
> -	enum charge_type type = MEM_CGROUP_CHARGE_TYPE_CACHE;
> -	int ret;
> -
> -	if (mem_cgroup_disabled())
> -		return 0;
> -	if (PageCompound(page))
> -		return 0;
> -
> -	if (unlikely(!mm))
> -		mm = &init_mm;
> -	if (!page_is_file_cache(page))
> -		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
> -
> -	if (!PageSwapCache(page))
> -		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
> -	else { /* page is swapcache/shmem */
> -		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg);
> -		if (!ret)
> -			__mem_cgroup_commit_charge_swapin(page, memcg, type);
> -	}
> -	return ret;
> -}
> -
>  /*
>   * While swap-in, try_charge -> commit or cancel, the page is locked.
>   * And when try_charge() successfully returns, one refcnt to memcg without
> @@ -2806,6 +2775,15 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>  	return ret;
>  }
>  
> +void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg)
> +{
> +	if (mem_cgroup_disabled())
> +		return;
> +	if (!memcg)
> +		return;
> +	__mem_cgroup_cancel_charge(memcg, 1);
> +}
> +
>  static void
>  __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *memcg,
>  					enum charge_type ctype)
> @@ -2843,13 +2821,31 @@ void mem_cgroup_commit_charge_swapin(struct page *page,
>  					  MEM_CGROUP_CHARGE_TYPE_ANON);
>  }
>  
> -void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg)
> +int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
> +				gfp_t gfp_mask)
>  {
> +	struct mem_cgroup *memcg = NULL;
> +	enum charge_type type = MEM_CGROUP_CHARGE_TYPE_CACHE;
> +	int ret;
> +
>  	if (mem_cgroup_disabled())
> -		return;
> -	if (!memcg)
> -		return;
> -	__mem_cgroup_cancel_charge(memcg, 1);
> +		return 0;
> +	if (PageCompound(page))
> +		return 0;
> +
> +	if (unlikely(!mm))
> +		mm = &init_mm;
> +	if (!page_is_file_cache(page))
> +		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
> +
> +	if (!PageSwapCache(page))
> +		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
> +	else { /* page is swapcache/shmem */
> +		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg);
> +		if (!ret)
> +			__mem_cgroup_commit_charge_swapin(page, memcg, type);
> +	}
> +	return ret;
>  }
>  
>  static void mem_cgroup_do_uncharge(struct mem_cgroup *memcg,
> -- 
> 1.7.7.6
> 

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 07/11] mm: memcg: remove unneeded shmem charge type
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09 15:17     ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:17 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:59, Johannes Weiner wrote:
> shmem page charges have not needed a separate charge type to tell them
> from regular file pages since 08e552c 'memcg: synchronized LRU'.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Yes, MEM_CGROUP_CHARGE_TYPE_SHMEM has been quite confusing.

Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   11 +----------
>  1 files changed, 1 insertions(+), 10 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 4a41b55..418b47d 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -379,7 +379,6 @@ static bool move_file(void)
>  enum charge_type {
>  	MEM_CGROUP_CHARGE_TYPE_CACHE = 0,
>  	MEM_CGROUP_CHARGE_TYPE_ANON,
> -	MEM_CGROUP_CHARGE_TYPE_SHMEM,	/* used by page migration of shmem */
>  	MEM_CGROUP_CHARGE_TYPE_SWAPOUT,	/* for accounting swapcache */
>  	MEM_CGROUP_CHARGE_TYPE_DROP,	/* a page was unused swap cache */
>  	NR_CHARGE_TYPE,
> @@ -2835,8 +2834,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
>  
>  	if (unlikely(!mm))
>  		mm = &init_mm;
> -	if (!page_is_file_cache(page))
> -		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
>  
>  	if (!PageSwapCache(page))
>  		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
> @@ -3243,10 +3240,8 @@ void mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
>  	 */
>  	if (PageAnon(page))
>  		ctype = MEM_CGROUP_CHARGE_TYPE_ANON;
> -	else if (page_is_file_cache(page))
> -		ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
>  	else
> -		ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
> +		ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
>  	/*
>  	 * The page is committed to the memcg, but it's not actually
>  	 * charged to the res_counter since we plan on replacing the
> @@ -3340,10 +3335,6 @@ void mem_cgroup_replace_page_cache(struct page *oldpage,
>  	 */
>  	if (!memcg)
>  		return;
> -
> -	if (PageSwapBacked(oldpage))
> -		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
> -
>  	/*
>  	 * Even if newpage->mapping was NULL before starting replacement,
>  	 * the newpage may be on LRU(or pagevec for LRU) already. We lock
> -- 
> 1.7.7.6
> 

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 07/11] mm: memcg: remove unneeded shmem charge type
@ 2012-07-09 15:17     ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:17 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:59, Johannes Weiner wrote:
> shmem page charges have not needed a separate charge type to tell them
> from regular file pages since 08e552c 'memcg: synchronized LRU'.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Yes, MEM_CGROUP_CHARGE_TYPE_SHMEM has been quite confusing.

Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   11 +----------
>  1 files changed, 1 insertions(+), 10 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 4a41b55..418b47d 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -379,7 +379,6 @@ static bool move_file(void)
>  enum charge_type {
>  	MEM_CGROUP_CHARGE_TYPE_CACHE = 0,
>  	MEM_CGROUP_CHARGE_TYPE_ANON,
> -	MEM_CGROUP_CHARGE_TYPE_SHMEM,	/* used by page migration of shmem */
>  	MEM_CGROUP_CHARGE_TYPE_SWAPOUT,	/* for accounting swapcache */
>  	MEM_CGROUP_CHARGE_TYPE_DROP,	/* a page was unused swap cache */
>  	NR_CHARGE_TYPE,
> @@ -2835,8 +2834,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
>  
>  	if (unlikely(!mm))
>  		mm = &init_mm;
> -	if (!page_is_file_cache(page))
> -		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
>  
>  	if (!PageSwapCache(page))
>  		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
> @@ -3243,10 +3240,8 @@ void mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
>  	 */
>  	if (PageAnon(page))
>  		ctype = MEM_CGROUP_CHARGE_TYPE_ANON;
> -	else if (page_is_file_cache(page))
> -		ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
>  	else
> -		ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
> +		ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
>  	/*
>  	 * The page is committed to the memcg, but it's not actually
>  	 * charged to the res_counter since we plan on replacing the
> @@ -3340,10 +3335,6 @@ void mem_cgroup_replace_page_cache(struct page *oldpage,
>  	 */
>  	if (!memcg)
>  		return;
> -
> -	if (PageSwapBacked(oldpage))
> -		type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
> -
>  	/*
>  	 * Even if newpage->mapping was NULL before starting replacement,
>  	 * the newpage may be on LRU(or pagevec for LRU) already. We lock
> -- 
> 1.7.7.6
> 

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
  2012-07-05  0:45   ` Johannes Weiner
@ 2012-07-09 15:20     ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:20 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:45:00, Johannes Weiner wrote:
> It does not matter to __mem_cgroup_try_charge() if the passed mm is
> NULL or init_mm, it will charge the root memcg in either case.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |    5 -----
>  1 files changed, 0 insertions(+), 5 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 418b47d..6fe4101 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2766,8 +2766,6 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>  		ret = 0;
>  	return ret;
>  charge_cur_mm:
> -	if (unlikely(!mm))
> -		mm = &init_mm;
>  	ret = __mem_cgroup_try_charge(mm, mask, 1, memcgp, true);
>  	if (ret == -EINTR)
>  		ret = 0;
> @@ -2832,9 +2830,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
>  	if (PageCompound(page))
>  		return 0;
>  
> -	if (unlikely(!mm))
> -		mm = &init_mm;
> -
>  	if (!PageSwapCache(page))
>  		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
>  	else { /* page is swapcache/shmem */
> -- 
> 1.7.7.6
> 

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
@ 2012-07-09 15:20     ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:20 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:45:00, Johannes Weiner wrote:
> It does not matter to __mem_cgroup_try_charge() if the passed mm is
> NULL or init_mm, it will charge the root memcg in either case.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |    5 -----
>  1 files changed, 0 insertions(+), 5 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 418b47d..6fe4101 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2766,8 +2766,6 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>  		ret = 0;
>  	return ret;
>  charge_cur_mm:
> -	if (unlikely(!mm))
> -		mm = &init_mm;
>  	ret = __mem_cgroup_try_charge(mm, mask, 1, memcgp, true);
>  	if (ret == -EINTR)
>  		ret = 0;
> @@ -2832,9 +2830,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
>  	if (PageCompound(page))
>  		return 0;
>  
> -	if (unlikely(!mm))
> -		mm = &init_mm;
> -
>  	if (!PageSwapCache(page))
>  		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
>  	else { /* page is swapcache/shmem */
> -- 
> 1.7.7.6
> 

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 09/11] mm: memcg: split swapin charge function into private and public part
  2012-07-05  0:45   ` Johannes Weiner
@ 2012-07-09 15:28     ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:28 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:45:01, Johannes Weiner wrote:
> When shmem is charged upon swapin, it does not need to check twice
> whether the memory controller is enabled.
> 
> Also, shmem pages do not have to be checked for everything that
> regular anon pages have to be checked for, so let shmem use the
> internal version directly and allow future patches to move around
> checks that are only required when swapping in anon pages.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   24 +++++++++++++++---------
>  1 files changed, 15 insertions(+), 9 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 6fe4101..a8bf86a 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2734,18 +2734,14 @@ int mem_cgroup_newpage_charge(struct page *page,
>   * struct page_cgroup is acquired. This refcnt will be consumed by
>   * "commit()" or removed by "cancel()"
>   */
> -int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
> -				 struct page *page,
> -				 gfp_t mask, struct mem_cgroup **memcgp)
> +static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm,
> +					  struct page *page,
> +					  gfp_t mask,
> +					  struct mem_cgroup **memcgp)
>  {
>  	struct mem_cgroup *memcg;
>  	int ret;
>  
> -	*memcgp = NULL;
> -
> -	if (mem_cgroup_disabled())
> -		return 0;
> -
>  	if (!do_swap_account)
>  		goto charge_cur_mm;
>  	/*
> @@ -2772,6 +2768,15 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>  	return ret;
>  }
>  
> +int mem_cgroup_try_charge_swapin(struct mm_struct *mm, struct page *page,
> +				 gfp_t gfp_mask, struct mem_cgroup **memcgp)
> +{
> +	*memcgp = NULL;
> +	if (mem_cgroup_disabled())
> +		return 0;
> +	return __mem_cgroup_try_charge_swapin(mm, page, gfp_mask, memcgp);
> +}
> +
>  void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg)
>  {
>  	if (mem_cgroup_disabled())
> @@ -2833,7 +2838,8 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
>  	if (!PageSwapCache(page))
>  		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
>  	else { /* page is swapcache/shmem */
> -		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg);
> +		ret = __mem_cgroup_try_charge_swapin(mm, page,
> +						     gfp_mask, &memcg);
>  		if (!ret)
>  			__mem_cgroup_commit_charge_swapin(page, memcg, type);
>  	}
> -- 
> 1.7.7.6
> 

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 09/11] mm: memcg: split swapin charge function into private and public part
@ 2012-07-09 15:28     ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:28 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:45:01, Johannes Weiner wrote:
> When shmem is charged upon swapin, it does not need to check twice
> whether the memory controller is enabled.
> 
> Also, shmem pages do not have to be checked for everything that
> regular anon pages have to be checked for, so let shmem use the
> internal version directly and allow future patches to move around
> checks that are only required when swapping in anon pages.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   24 +++++++++++++++---------
>  1 files changed, 15 insertions(+), 9 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 6fe4101..a8bf86a 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2734,18 +2734,14 @@ int mem_cgroup_newpage_charge(struct page *page,
>   * struct page_cgroup is acquired. This refcnt will be consumed by
>   * "commit()" or removed by "cancel()"
>   */
> -int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
> -				 struct page *page,
> -				 gfp_t mask, struct mem_cgroup **memcgp)
> +static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm,
> +					  struct page *page,
> +					  gfp_t mask,
> +					  struct mem_cgroup **memcgp)
>  {
>  	struct mem_cgroup *memcg;
>  	int ret;
>  
> -	*memcgp = NULL;
> -
> -	if (mem_cgroup_disabled())
> -		return 0;
> -
>  	if (!do_swap_account)
>  		goto charge_cur_mm;
>  	/*
> @@ -2772,6 +2768,15 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>  	return ret;
>  }
>  
> +int mem_cgroup_try_charge_swapin(struct mm_struct *mm, struct page *page,
> +				 gfp_t gfp_mask, struct mem_cgroup **memcgp)
> +{
> +	*memcgp = NULL;
> +	if (mem_cgroup_disabled())
> +		return 0;
> +	return __mem_cgroup_try_charge_swapin(mm, page, gfp_mask, memcgp);
> +}
> +
>  void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg)
>  {
>  	if (mem_cgroup_disabled())
> @@ -2833,7 +2838,8 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
>  	if (!PageSwapCache(page))
>  		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
>  	else { /* page is swapcache/shmem */
> -		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg);
> +		ret = __mem_cgroup_try_charge_swapin(mm, page,
> +						     gfp_mask, &memcg);
>  		if (!ret)
>  			__mem_cgroup_commit_charge_swapin(page, memcg, type);
>  	}
> -- 
> 1.7.7.6
> 

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 10/11] mm: memcg: only check swap cache pages for repeated charging
  2012-07-05  0:45   ` Johannes Weiner
@ 2012-07-09 15:32     ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:32 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:45:02, Johannes Weiner wrote:
> Only anon and shmem pages in the swap cache are attempted to be
> charged multiple times, from every swap pte fault or from
> shmem_unuse().  No other pages require checking PageCgroupUsed().
> 
> Charging pages in the swap cache is also serialized by the page lock,
> and since both the try_charge and commit_charge are called under the
> same page lock section, the PageCgroupUsed() check might as well
> happen before the counter charging, let alone reclaim.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   17 ++++++++++++-----
>  1 files changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index a8bf86a..d3701cd 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2471,11 +2471,7 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
>  	bool anon;
>  
>  	lock_page_cgroup(pc);
> -	if (unlikely(PageCgroupUsed(pc))) {
> -		unlock_page_cgroup(pc);
> -		__mem_cgroup_cancel_charge(memcg, nr_pages);
> -		return;
> -	}
> +	VM_BUG_ON(PageCgroupUsed(pc));
>  	/*
>  	 * we don't need page_cgroup_lock about tail pages, becase they are not
>  	 * accessed by any other context at this point.
> @@ -2740,8 +2736,19 @@ static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>  					  struct mem_cgroup **memcgp)
>  {
>  	struct mem_cgroup *memcg;
> +	struct page_cgroup *pc;
>  	int ret;
>  
> +	pc = lookup_page_cgroup(page);
> +	/*
> +	 * Every swap fault against a single page tries to charge the
> +	 * page, bail as early as possible.  shmem_unuse() encounters
> +	 * already charged pages, too.  The USED bit is protected by
> +	 * the page lock, which serializes swap cache removal, which
> +	 * in turn serializes uncharging.
> +	 */
> +	if (PageCgroupUsed(pc))
> +		return 0;
>  	if (!do_swap_account)
>  		goto charge_cur_mm;
>  	/*
> -- 
> 1.7.7.6
> 

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 10/11] mm: memcg: only check swap cache pages for repeated charging
@ 2012-07-09 15:32     ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:32 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:45:02, Johannes Weiner wrote:
> Only anon and shmem pages in the swap cache are attempted to be
> charged multiple times, from every swap pte fault or from
> shmem_unuse().  No other pages require checking PageCgroupUsed().
> 
> Charging pages in the swap cache is also serialized by the page lock,
> and since both the try_charge and commit_charge are called under the
> same page lock section, the PageCgroupUsed() check might as well
> happen before the counter charging, let alone reclaim.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   17 ++++++++++++-----
>  1 files changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index a8bf86a..d3701cd 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2471,11 +2471,7 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
>  	bool anon;
>  
>  	lock_page_cgroup(pc);
> -	if (unlikely(PageCgroupUsed(pc))) {
> -		unlock_page_cgroup(pc);
> -		__mem_cgroup_cancel_charge(memcg, nr_pages);
> -		return;
> -	}
> +	VM_BUG_ON(PageCgroupUsed(pc));
>  	/*
>  	 * we don't need page_cgroup_lock about tail pages, becase they are not
>  	 * accessed by any other context at this point.
> @@ -2740,8 +2736,19 @@ static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>  					  struct mem_cgroup **memcgp)
>  {
>  	struct mem_cgroup *memcg;
> +	struct page_cgroup *pc;
>  	int ret;
>  
> +	pc = lookup_page_cgroup(page);
> +	/*
> +	 * Every swap fault against a single page tries to charge the
> +	 * page, bail as early as possible.  shmem_unuse() encounters
> +	 * already charged pages, too.  The USED bit is protected by
> +	 * the page lock, which serializes swap cache removal, which
> +	 * in turn serializes uncharging.
> +	 */
> +	if (PageCgroupUsed(pc))
> +		return 0;
>  	if (!do_swap_account)
>  		goto charge_cur_mm;
>  	/*
> -- 
> 1.7.7.6
> 

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 11/11] mm: memcg: only check anon swapin page charges for swap cache
  2012-07-05  0:45   ` Johannes Weiner
@ 2012-07-09 15:34     ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:34 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:45:03, Johannes Weiner wrote:
> shmem knows for sure that the page is in swap cache when attempting to
> charge a page, because the cache charge entry function has a check for
> it.  Only anon pages may be removed from swap cache already when
> trying to charge their swapin.
> 
> Adjust the comment, though: '4969c11 mm: fix swapin race condition'
> added a stable PageSwapCache check under the page lock in the
> do_swap_page() before calling the memory controller, so it's
> unuse_pte()'s pte_same() that may fail.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Looks good
Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   22 ++++++++++++++--------
>  1 files changed, 14 insertions(+), 8 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index d3701cd..9b7e256 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2751,14 +2751,6 @@ static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>  		return 0;
>  	if (!do_swap_account)
>  		goto charge_cur_mm;
> -	/*
> -	 * A racing thread's fault, or swapoff, may have already updated
> -	 * the pte, and even removed page from swap cache: in those cases
> -	 * do_swap_page()'s pte_same() test will fail; but there's also a
> -	 * KSM case which does need to charge the page.
> -	 */
> -	if (!PageSwapCache(page))
> -		goto charge_cur_mm;
>  	memcg = try_get_mem_cgroup_from_page(page);
>  	if (!memcg)
>  		goto charge_cur_mm;
> @@ -2781,6 +2773,20 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm, struct page *page,
>  	*memcgp = NULL;
>  	if (mem_cgroup_disabled())
>  		return 0;
> +	/*
> +	 * A racing thread's fault, or swapoff, may have already
> +	 * updated the pte, and even removed page from swap cache: in
> +	 * those cases unuse_pte()'s pte_same() test will fail; but
> +	 * there's also a KSM case which does need to charge the page.
> +	 */
> +	if (!PageSwapCache(page)) {
> +		int ret;
> +
> +		ret = __mem_cgroup_try_charge(mm, gfp_mask, 1, memcgp, true);
> +		if (ret == -EINTR)
> +			ret = 0;
> +		return ret;
> +	}
>  	return __mem_cgroup_try_charge_swapin(mm, page, gfp_mask, memcgp);
>  }
>  
> -- 
> 1.7.7.6
> 

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 11/11] mm: memcg: only check anon swapin page charges for swap cache
@ 2012-07-09 15:34     ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:34 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:45:03, Johannes Weiner wrote:
> shmem knows for sure that the page is in swap cache when attempting to
> charge a page, because the cache charge entry function has a check for
> it.  Only anon pages may be removed from swap cache already when
> trying to charge their swapin.
> 
> Adjust the comment, though: '4969c11 mm: fix swapin race condition'
> added a stable PageSwapCache check under the page lock in the
> do_swap_page() before calling the memory controller, so it's
> unuse_pte()'s pte_same() that may fail.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>

Looks good
Acked-by: Michal Hocko <mhocko@suse.cz>

> ---
>  mm/memcontrol.c |   22 ++++++++++++++--------
>  1 files changed, 14 insertions(+), 8 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index d3701cd..9b7e256 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2751,14 +2751,6 @@ static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>  		return 0;
>  	if (!do_swap_account)
>  		goto charge_cur_mm;
> -	/*
> -	 * A racing thread's fault, or swapoff, may have already updated
> -	 * the pte, and even removed page from swap cache: in those cases
> -	 * do_swap_page()'s pte_same() test will fail; but there's also a
> -	 * KSM case which does need to charge the page.
> -	 */
> -	if (!PageSwapCache(page))
> -		goto charge_cur_mm;
>  	memcg = try_get_mem_cgroup_from_page(page);
>  	if (!memcg)
>  		goto charge_cur_mm;
> @@ -2781,6 +2773,20 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm, struct page *page,
>  	*memcgp = NULL;
>  	if (mem_cgroup_disabled())
>  		return 0;
> +	/*
> +	 * A racing thread's fault, or swapoff, may have already
> +	 * updated the pte, and even removed page from swap cache: in
> +	 * those cases unuse_pte()'s pte_same() test will fail; but
> +	 * there's also a KSM case which does need to charge the page.
> +	 */
> +	if (!PageSwapCache(page)) {
> +		int ret;
> +
> +		ret = __mem_cgroup_try_charge(mm, gfp_mask, 1, memcgp, true);
> +		if (ret == -EINTR)
> +			ret = 0;
> +		return ret;
> +	}
>  	return __mem_cgroup_try_charge_swapin(mm, page, gfp_mask, memcgp);
>  }
>  
> -- 
> 1.7.7.6
> 

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 00/11] mm: memcg: charge/uncharge improvements
  2012-07-05  0:44 ` Johannes Weiner
@ 2012-07-09 15:35   ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:35 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:52, Johannes Weiner wrote:
> Hello,
> 
> the biggest thing is probably #1, no longer trying (and failing) to
> charge replacement pages during migration and thus compaction.  The
> rest is cleanups and tiny optimizations that move some checks out of
> the charge and uncharge core paths that do not apply to all types of
> pages alike.

Nice clean up Johannes.
Thanks!

> 
>  include/linux/memcontrol.h |   11 +--
>  mm/memcontrol.c            |  205 +++++++++++++++++++++++---------------------
>  mm/migrate.c               |   27 ++-----
>  mm/shmem.c                 |   11 ++-
>  mm/swapfile.c              |    3 +-
>  5 files changed, 124 insertions(+), 133 deletions(-)
> 

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 00/11] mm: memcg: charge/uncharge improvements
@ 2012-07-09 15:35   ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-09 15:35 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu 05-07-12 02:44:52, Johannes Weiner wrote:
> Hello,
> 
> the biggest thing is probably #1, no longer trying (and failing) to
> charge replacement pages during migration and thus compaction.  The
> rest is cleanups and tiny optimizations that move some checks out of
> the charge and uncharge core paths that do not apply to all types of
> pages alike.

Nice clean up Johannes.
Thanks!

> 
>  include/linux/memcontrol.h |   11 +--
>  mm/memcontrol.c            |  205 +++++++++++++++++++++++---------------------
>  mm/migrate.c               |   27 ++-----
>  mm/shmem.c                 |   11 ++-
>  mm/swapfile.c              |    3 +-
>  5 files changed, 124 insertions(+), 133 deletions(-)
> 

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
  2012-07-05  0:44   ` Johannes Weiner
@ 2012-07-09 20:11     ` Hugh Dickins
  -1 siblings, 0 replies; 90+ messages in thread
From: Hugh Dickins @ 2012-07-09 20:11 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Michal Hocko, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu, 5 Jul 2012, Johannes Weiner wrote:
> Once charged, swapcache pages can only be uncharged after they are
> removed from swapcache again.
> 
> Do not try to uncharge pages that are known to be in the swapcache, to
> allow future patches to remove checks for that in the uncharge code.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> ---
>  mm/shmem.c |   11 ++++++-----
>  1 files changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/mm/shmem.c b/mm/shmem.c
> index ee1c5a2..d12b705 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -302,8 +302,6 @@ static int shmem_add_to_page_cache(struct page *page,
>  		if (!expected)
>  			radix_tree_preload_end();
>  	}
> -	if (error)
> -		mem_cgroup_uncharge_cache_page(page);
>  	return error;
>  }
>  
> @@ -1184,11 +1182,14 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
>  		__set_page_locked(page);
>  		error = mem_cgroup_cache_charge(page, current->mm,
>  						gfp & GFP_RECLAIM_MASK);
> -		if (!error)
> -			error = shmem_add_to_page_cache(page, mapping, index,
> -						gfp, NULL);
>  		if (error)
>  			goto decused;
> +		error = shmem_add_to_page_cache(page, mapping, index,
> +						gfp, NULL);
> +		if (error) {
> +			mem_cgroup_uncharge_cache_page(page);
> +			goto decused;
> +		}
>  		lru_cache_add_anon(page);
>  
>  		spin_lock(&info->lock);
> -- 

I wanted to try this series out on mmotm before replying, and that
took a while; but the problems (some experimental RCU stuff, since
reverted; and Michal's wait_on_page_writeback in vmscan.c, I'll have
to investigate that later) were in mmotm rather than your series:
seems to be running fine under load now.

I've not reviewed, but definitely approve avoiding the temporary
extra charge in migration, and your other simplifications.

And I do approve this change, but selfishly withhold my Ack because
it's a subset of small shmem.c changes I was already lining up to
post, hoping still to sneak into 3.5.  We have a real bug in there
(charging to wrong memcg), and this cleanup comes along with that.
I'll post my version in an hour or two.

Hugh

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
@ 2012-07-09 20:11     ` Hugh Dickins
  0 siblings, 0 replies; 90+ messages in thread
From: Hugh Dickins @ 2012-07-09 20:11 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Andrew Morton, KAMEZAWA Hiroyuki, Michal Hocko, David Rientjes,
	linux-mm, cgroups, linux-kernel

On Thu, 5 Jul 2012, Johannes Weiner wrote:
> Once charged, swapcache pages can only be uncharged after they are
> removed from swapcache again.
> 
> Do not try to uncharge pages that are known to be in the swapcache, to
> allow future patches to remove checks for that in the uncharge code.
> 
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> ---
>  mm/shmem.c |   11 ++++++-----
>  1 files changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/mm/shmem.c b/mm/shmem.c
> index ee1c5a2..d12b705 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -302,8 +302,6 @@ static int shmem_add_to_page_cache(struct page *page,
>  		if (!expected)
>  			radix_tree_preload_end();
>  	}
> -	if (error)
> -		mem_cgroup_uncharge_cache_page(page);
>  	return error;
>  }
>  
> @@ -1184,11 +1182,14 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
>  		__set_page_locked(page);
>  		error = mem_cgroup_cache_charge(page, current->mm,
>  						gfp & GFP_RECLAIM_MASK);
> -		if (!error)
> -			error = shmem_add_to_page_cache(page, mapping, index,
> -						gfp, NULL);
>  		if (error)
>  			goto decused;
> +		error = shmem_add_to_page_cache(page, mapping, index,
> +						gfp, NULL);
> +		if (error) {
> +			mem_cgroup_uncharge_cache_page(page);
> +			goto decused;
> +		}
>  		lru_cache_add_anon(page);
>  
>  		spin_lock(&info->lock);
> -- 

I wanted to try this series out on mmotm before replying, and that
took a while; but the problems (some experimental RCU stuff, since
reverted; and Michal's wait_on_page_writeback in vmscan.c, I'll have
to investigate that later) were in mmotm rather than your series:
seems to be running fine under load now.

I've not reviewed, but definitely approve avoiding the temporary
extra charge in migration, and your other simplifications.

And I do approve this change, but selfishly withhold my Ack because
it's a subset of small shmem.c changes I was already lining up to
post, hoping still to sneak into 3.5.  We have a real bug in there
(charging to wrong memcg), and this cleanup comes along with that.
I'll post my version in an hour or two.

Hugh

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
  2012-07-09 14:46     ` Michal Hocko
@ 2012-07-09 20:37       ` Hugh Dickins
  -1 siblings, 0 replies; 90+ messages in thread
From: Hugh Dickins @ 2012-07-09 20:37 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki,
	David Rientjes, linux-mm, cgroups, linux-kernel

On Mon, 9 Jul 2012, Michal Hocko wrote:
> 
> Maybe I am missing something but who does the uncharge from:
> shmem_unuse
>   mem_cgroup_cache_charge
>   shmem_unuse_inode
>     shmem_add_to_page_cache

There isn't any special uncharge for shmem_unuse(): once the swapcache
page is matched up with its memcg, it will get uncharged by one of the
usual routes to swapcache_free() when the page is freed: maybe in the
call from __remove_mapping(), maybe when free_page_and_swap_cache()
ends up calling it.

Perhaps you're worrying about error (or unfound) paths in shmem_unuse()?
By the time we make the charge, we know for sure that it's a shmem page,
and make the charge appropriately; in racy cases it might get uncharged
again in the delete_from_swap_cache().  Can the unfound case occur these
days?  I'd have to think more deeply to answer that, but the charge will
not go missing.

Hugh

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
@ 2012-07-09 20:37       ` Hugh Dickins
  0 siblings, 0 replies; 90+ messages in thread
From: Hugh Dickins @ 2012-07-09 20:37 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki,
	David Rientjes, linux-mm, cgroups, linux-kernel

On Mon, 9 Jul 2012, Michal Hocko wrote:
> 
> Maybe I am missing something but who does the uncharge from:
> shmem_unuse
>   mem_cgroup_cache_charge
>   shmem_unuse_inode
>     shmem_add_to_page_cache

There isn't any special uncharge for shmem_unuse(): once the swapcache
page is matched up with its memcg, it will get uncharged by one of the
usual routes to swapcache_free() when the page is freed: maybe in the
call from __remove_mapping(), maybe when free_page_and_swap_cache()
ends up calling it.

Perhaps you're worrying about error (or unfound) paths in shmem_unuse()?
By the time we make the charge, we know for sure that it's a shmem page,
and make the charge appropriately; in racy cases it might get uncharged
again in the delete_from_swap_cache().  Can the unfound case occur these
days?  I'd have to think more deeply to answer that, but the charge will
not go missing.

Hugh

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
  2012-07-09 15:20     ` Michal Hocko
@ 2012-07-10  6:10       ` Wanpeng Li
  -1 siblings, 0 replies; 90+ messages in thread
From: Wanpeng Li @ 2012-07-10  6:10 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Michal Hocko, Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins,
	David Rientjes, linux-mm, cgroups, linux-kernel, Wanpeng Li

On Mon, Jul 09, 2012 at 05:20:58PM +0200, Michal Hocko wrote:
>On Thu 05-07-12 02:45:00, Johannes Weiner wrote:
>> It does not matter to __mem_cgroup_try_charge() if the passed mm is
>> NULL or init_mm, it will charge the root memcg in either case.

You can also change the comment in __mem_cgroup_try_charge :

"if so charge the init_mm" => "if so charge the root memcg"

>> 
>> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
>
>Acked-by: Michal Hocko <mhocko@suse.cz>
>
>> ---
>>  mm/memcontrol.c |    5 -----
>>  1 files changed, 0 insertions(+), 5 deletions(-)
>> 
>> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
>> index 418b47d..6fe4101 100644
>> --- a/mm/memcontrol.c
>> +++ b/mm/memcontrol.c
>> @@ -2766,8 +2766,6 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>>  		ret = 0;
>>  	return ret;
>>  charge_cur_mm:
>> -	if (unlikely(!mm))
>> -		mm = &init_mm;
>>  	ret = __mem_cgroup_try_charge(mm, mask, 1, memcgp, true);
>>  	if (ret == -EINTR)
>>  		ret = 0;
>> @@ -2832,9 +2830,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
>>  	if (PageCompound(page))
>>  		return 0;
>>  
>> -	if (unlikely(!mm))
>> -		mm = &init_mm;
>> -
>>  	if (!PageSwapCache(page))
>>  		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
>>  	else { /* page is swapcache/shmem */
>> -- 
>> 1.7.7.6
>> 
>
>-- 
>Michal Hocko
>SUSE Labs
>SUSE LINUX s.r.o.
>Lihovarska 1060/12
>190 00 Praha 9    
>Czech Republic
>--
>To unsubscribe from this list: send the line "unsubscribe cgroups" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
@ 2012-07-10  6:10       ` Wanpeng Li
  0 siblings, 0 replies; 90+ messages in thread
From: Wanpeng Li @ 2012-07-10  6:10 UTC (permalink / raw)
  To: Johannes Weiner
  Cc: Michal Hocko, Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins,
	David Rientjes, linux-mm, cgroups, linux-kernel, Wanpeng Li

On Mon, Jul 09, 2012 at 05:20:58PM +0200, Michal Hocko wrote:
>On Thu 05-07-12 02:45:00, Johannes Weiner wrote:
>> It does not matter to __mem_cgroup_try_charge() if the passed mm is
>> NULL or init_mm, it will charge the root memcg in either case.

You can also change the comment in __mem_cgroup_try_charge :

"if so charge the init_mm" => "if so charge the root memcg"

>> 
>> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
>
>Acked-by: Michal Hocko <mhocko@suse.cz>
>
>> ---
>>  mm/memcontrol.c |    5 -----
>>  1 files changed, 0 insertions(+), 5 deletions(-)
>> 
>> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
>> index 418b47d..6fe4101 100644
>> --- a/mm/memcontrol.c
>> +++ b/mm/memcontrol.c
>> @@ -2766,8 +2766,6 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>>  		ret = 0;
>>  	return ret;
>>  charge_cur_mm:
>> -	if (unlikely(!mm))
>> -		mm = &init_mm;
>>  	ret = __mem_cgroup_try_charge(mm, mask, 1, memcgp, true);
>>  	if (ret == -EINTR)
>>  		ret = 0;
>> @@ -2832,9 +2830,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
>>  	if (PageCompound(page))
>>  		return 0;
>>  
>> -	if (unlikely(!mm))
>> -		mm = &init_mm;
>> -
>>  	if (!PageSwapCache(page))
>>  		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
>>  	else { /* page is swapcache/shmem */
>> -- 
>> 1.7.7.6
>> 
>
>-- 
>Michal Hocko
>SUSE Labs
>SUSE LINUX s.r.o.
>Lihovarska 1060/12
>190 00 Praha 9    
>Czech Republic
>--
>To unsubscribe from this list: send the line "unsubscribe cgroups" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
  2012-07-10  6:10       ` Wanpeng Li
@ 2012-07-10  6:21         ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-10  6:21 UTC (permalink / raw)
  To: Wanpeng Li
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins,
	David Rientjes, linux-mm, cgroups, linux-kernel

On Tue 10-07-12 14:10:21, Wanpeng Li wrote:
> On Mon, Jul 09, 2012 at 05:20:58PM +0200, Michal Hocko wrote:
> >On Thu 05-07-12 02:45:00, Johannes Weiner wrote:
> >> It does not matter to __mem_cgroup_try_charge() if the passed mm is
> >> NULL or init_mm, it will charge the root memcg in either case.
> 
> You can also change the comment in __mem_cgroup_try_charge :
> 
> "if so charge the init_mm" => "if so charge the root memcg"

This is already in place:
"
If mm is NULL and the caller doesn't pass a valid memcg pointer, that is
treated as a charge to root_mem_cgroup.
"
> 
> >> 
> >> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> >
> >Acked-by: Michal Hocko <mhocko@suse.cz>
> >
> >> ---
> >>  mm/memcontrol.c |    5 -----
> >>  1 files changed, 0 insertions(+), 5 deletions(-)
> >> 
> >> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> >> index 418b47d..6fe4101 100644
> >> --- a/mm/memcontrol.c
> >> +++ b/mm/memcontrol.c
> >> @@ -2766,8 +2766,6 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
> >>  		ret = 0;
> >>  	return ret;
> >>  charge_cur_mm:
> >> -	if (unlikely(!mm))
> >> -		mm = &init_mm;
> >>  	ret = __mem_cgroup_try_charge(mm, mask, 1, memcgp, true);
> >>  	if (ret == -EINTR)
> >>  		ret = 0;
> >> @@ -2832,9 +2830,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
> >>  	if (PageCompound(page))
> >>  		return 0;
> >>  
> >> -	if (unlikely(!mm))
> >> -		mm = &init_mm;
> >> -
> >>  	if (!PageSwapCache(page))
> >>  		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
> >>  	else { /* page is swapcache/shmem */
> >> -- 
> >> 1.7.7.6
> >> 
> >
> >-- 
> >Michal Hocko
> >SUSE Labs
> >SUSE LINUX s.r.o.
> >Lihovarska 1060/12
> >190 00 Praha 9    
> >Czech Republic
> >--
> >To unsubscribe from this list: send the line "unsubscribe cgroups" in
> >the body of a message to majordomo@vger.kernel.org
> >More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
@ 2012-07-10  6:21         ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-10  6:21 UTC (permalink / raw)
  To: Wanpeng Li
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins,
	David Rientjes, linux-mm, cgroups, linux-kernel

On Tue 10-07-12 14:10:21, Wanpeng Li wrote:
> On Mon, Jul 09, 2012 at 05:20:58PM +0200, Michal Hocko wrote:
> >On Thu 05-07-12 02:45:00, Johannes Weiner wrote:
> >> It does not matter to __mem_cgroup_try_charge() if the passed mm is
> >> NULL or init_mm, it will charge the root memcg in either case.
> 
> You can also change the comment in __mem_cgroup_try_charge :
> 
> "if so charge the init_mm" => "if so charge the root memcg"

This is already in place:
"
If mm is NULL and the caller doesn't pass a valid memcg pointer, that is
treated as a charge to root_mem_cgroup.
"
> 
> >> 
> >> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> >
> >Acked-by: Michal Hocko <mhocko@suse.cz>
> >
> >> ---
> >>  mm/memcontrol.c |    5 -----
> >>  1 files changed, 0 insertions(+), 5 deletions(-)
> >> 
> >> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> >> index 418b47d..6fe4101 100644
> >> --- a/mm/memcontrol.c
> >> +++ b/mm/memcontrol.c
> >> @@ -2766,8 +2766,6 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
> >>  		ret = 0;
> >>  	return ret;
> >>  charge_cur_mm:
> >> -	if (unlikely(!mm))
> >> -		mm = &init_mm;
> >>  	ret = __mem_cgroup_try_charge(mm, mask, 1, memcgp, true);
> >>  	if (ret == -EINTR)
> >>  		ret = 0;
> >> @@ -2832,9 +2830,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
> >>  	if (PageCompound(page))
> >>  		return 0;
> >>  
> >> -	if (unlikely(!mm))
> >> -		mm = &init_mm;
> >> -
> >>  	if (!PageSwapCache(page))
> >>  		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
> >>  	else { /* page is swapcache/shmem */
> >> -- 
> >> 1.7.7.6
> >> 
> >
> >-- 
> >Michal Hocko
> >SUSE Labs
> >SUSE LINUX s.r.o.
> >Lihovarska 1060/12
> >190 00 Praha 9    
> >Czech Republic
> >--
> >To unsubscribe from this list: send the line "unsubscribe cgroups" in
> >the body of a message to majordomo@vger.kernel.org
> >More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
  2012-07-10  6:21         ` Michal Hocko
@ 2012-07-10  6:54           ` Wanpeng Li
  -1 siblings, 0 replies; 90+ messages in thread
From: Wanpeng Li @ 2012-07-10  6:54 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins,
	David Rientjes, linux-mm, cgroups, linux-kernel, Wanpeng Li

On Tue, Jul 10, 2012 at 08:21:04AM +0200, Michal Hocko wrote:
>On Tue 10-07-12 14:10:21, Wanpeng Li wrote:
>> On Mon, Jul 09, 2012 at 05:20:58PM +0200, Michal Hocko wrote:
>> >On Thu 05-07-12 02:45:00, Johannes Weiner wrote:
>> >> It does not matter to __mem_cgroup_try_charge() if the passed mm is
>> >> NULL or init_mm, it will charge the root memcg in either case.
>> 
>> You can also change the comment in __mem_cgroup_try_charge :
>> 
>> "if so charge the init_mm" => "if so charge the root memcg"
>
>This is already in place:
>"
>If mm is NULL and the caller doesn't pass a valid memcg pointer, that is
>treated as a charge to root_mem_cgroup.
>"

IIUC, if still keep comment "if so charge the init_mm" is not correct,
since pages in pagecache aren't mapped into any processes' ptes, 
so mm is NULL, and these pages which in pagecache are not belong 
to init_mm, the comment should be changed. :-)

>> 
>> >> 
>> >> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
>> >
>> >Acked-by: Michal Hocko <mhocko@suse.cz>
>> >
>> >> ---
>> >>  mm/memcontrol.c |    5 -----
>> >>  1 files changed, 0 insertions(+), 5 deletions(-)
>> >> 
>> >> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
>> >> index 418b47d..6fe4101 100644
>> >> --- a/mm/memcontrol.c
>> >> +++ b/mm/memcontrol.c
>> >> @@ -2766,8 +2766,6 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>> >>  		ret = 0;
>> >>  	return ret;
>> >>  charge_cur_mm:
>> >> -	if (unlikely(!mm))
>> >> -		mm = &init_mm;
>> >>  	ret = __mem_cgroup_try_charge(mm, mask, 1, memcgp, true);
>> >>  	if (ret == -EINTR)
>> >>  		ret = 0;
>> >> @@ -2832,9 +2830,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
>> >>  	if (PageCompound(page))
>> >>  		return 0;
>> >>  
>> >> -	if (unlikely(!mm))
>> >> -		mm = &init_mm;
>> >> -
>> >>  	if (!PageSwapCache(page))
>> >>  		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
>> >>  	else { /* page is swapcache/shmem */
>> >> -- 
>> >> 1.7.7.6
>> >> 
>> >
>> >-- 
>> >Michal Hocko
>> >SUSE Labs
>> >SUSE LINUX s.r.o.
>> >Lihovarska 1060/12
>> >190 00 Praha 9    
>> >Czech Republic
>> >--
>> >To unsubscribe from this list: send the line "unsubscribe cgroups" in
>> >the body of a message to majordomo@vger.kernel.org
>> >More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>-- 
>Michal Hocko
>SUSE Labs
>SUSE LINUX s.r.o.
>Lihovarska 1060/12
>190 00 Praha 9    
>Czech Republic

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
@ 2012-07-10  6:54           ` Wanpeng Li
  0 siblings, 0 replies; 90+ messages in thread
From: Wanpeng Li @ 2012-07-10  6:54 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins,
	David Rientjes, linux-mm, cgroups, linux-kernel, Wanpeng Li

On Tue, Jul 10, 2012 at 08:21:04AM +0200, Michal Hocko wrote:
>On Tue 10-07-12 14:10:21, Wanpeng Li wrote:
>> On Mon, Jul 09, 2012 at 05:20:58PM +0200, Michal Hocko wrote:
>> >On Thu 05-07-12 02:45:00, Johannes Weiner wrote:
>> >> It does not matter to __mem_cgroup_try_charge() if the passed mm is
>> >> NULL or init_mm, it will charge the root memcg in either case.
>> 
>> You can also change the comment in __mem_cgroup_try_charge :
>> 
>> "if so charge the init_mm" => "if so charge the root memcg"
>
>This is already in place:
>"
>If mm is NULL and the caller doesn't pass a valid memcg pointer, that is
>treated as a charge to root_mem_cgroup.
>"

IIUC, if still keep comment "if so charge the init_mm" is not correct,
since pages in pagecache aren't mapped into any processes' ptes, 
so mm is NULL, and these pages which in pagecache are not belong 
to init_mm, the comment should be changed. :-)

>> 
>> >> 
>> >> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
>> >
>> >Acked-by: Michal Hocko <mhocko@suse.cz>
>> >
>> >> ---
>> >>  mm/memcontrol.c |    5 -----
>> >>  1 files changed, 0 insertions(+), 5 deletions(-)
>> >> 
>> >> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
>> >> index 418b47d..6fe4101 100644
>> >> --- a/mm/memcontrol.c
>> >> +++ b/mm/memcontrol.c
>> >> @@ -2766,8 +2766,6 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
>> >>  		ret = 0;
>> >>  	return ret;
>> >>  charge_cur_mm:
>> >> -	if (unlikely(!mm))
>> >> -		mm = &init_mm;
>> >>  	ret = __mem_cgroup_try_charge(mm, mask, 1, memcgp, true);
>> >>  	if (ret == -EINTR)
>> >>  		ret = 0;
>> >> @@ -2832,9 +2830,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
>> >>  	if (PageCompound(page))
>> >>  		return 0;
>> >>  
>> >> -	if (unlikely(!mm))
>> >> -		mm = &init_mm;
>> >> -
>> >>  	if (!PageSwapCache(page))
>> >>  		ret = mem_cgroup_charge_common(page, mm, gfp_mask, type);
>> >>  	else { /* page is swapcache/shmem */
>> >> -- 
>> >> 1.7.7.6
>> >> 
>> >
>> >-- 
>> >Michal Hocko
>> >SUSE Labs
>> >SUSE LINUX s.r.o.
>> >Lihovarska 1060/12
>> >190 00 Praha 9    
>> >Czech Republic
>> >--
>> >To unsubscribe from this list: send the line "unsubscribe cgroups" in
>> >the body of a message to majordomo@vger.kernel.org
>> >More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>-- 
>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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
  2012-07-10  6:54           ` Wanpeng Li
@ 2012-07-10 16:22             ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-10 16:22 UTC (permalink / raw)
  To: Wanpeng Li
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins,
	David Rientjes, linux-mm, cgroups, linux-kernel

On Tue 10-07-12 14:54:48, Wanpeng Li wrote:
> On Tue, Jul 10, 2012 at 08:21:04AM +0200, Michal Hocko wrote:
> >On Tue 10-07-12 14:10:21, Wanpeng Li wrote:
> >> On Mon, Jul 09, 2012 at 05:20:58PM +0200, Michal Hocko wrote:
> >> >On Thu 05-07-12 02:45:00, Johannes Weiner wrote:
> >> >> It does not matter to __mem_cgroup_try_charge() if the passed mm is
> >> >> NULL or init_mm, it will charge the root memcg in either case.
> >> 
> >> You can also change the comment in __mem_cgroup_try_charge :
> >> 
> >> "if so charge the init_mm" => "if so charge the root memcg"
> >
> >This is already in place:
> >"
> >If mm is NULL and the caller doesn't pass a valid memcg pointer, that is
> >treated as a charge to root_mem_cgroup.
> >"
> 
> IIUC, if still keep comment "if so charge the init_mm" is not correct,
> since pages in pagecache aren't mapped into any processes' ptes, 
> so mm is NULL, and these pages which in pagecache are not belong 
> to init_mm, the comment should be changed. :-)

Fair enough. I guess Johannes will change that in the next post.
-- 
Michal Hocko
SUSE Labs
SUSE LINUX s.r.o.
Lihovarska 1060/12
190 00 Praha 9    
Czech Republic

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging
@ 2012-07-10 16:22             ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-10 16:22 UTC (permalink / raw)
  To: Wanpeng Li
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki, Hugh Dickins,
	David Rientjes, linux-mm, cgroups, linux-kernel

On Tue 10-07-12 14:54:48, Wanpeng Li wrote:
> On Tue, Jul 10, 2012 at 08:21:04AM +0200, Michal Hocko wrote:
> >On Tue 10-07-12 14:10:21, Wanpeng Li wrote:
> >> On Mon, Jul 09, 2012 at 05:20:58PM +0200, Michal Hocko wrote:
> >> >On Thu 05-07-12 02:45:00, Johannes Weiner wrote:
> >> >> It does not matter to __mem_cgroup_try_charge() if the passed mm is
> >> >> NULL or init_mm, it will charge the root memcg in either case.
> >> 
> >> You can also change the comment in __mem_cgroup_try_charge :
> >> 
> >> "if so charge the init_mm" => "if so charge the root memcg"
> >
> >This is already in place:
> >"
> >If mm is NULL and the caller doesn't pass a valid memcg pointer, that is
> >treated as a charge to root_mem_cgroup.
> >"
> 
> IIUC, if still keep comment "if so charge the init_mm" is not correct,
> since pages in pagecache aren't mapped into any processes' ptes, 
> so mm is NULL, and these pages which in pagecache are not belong 
> to init_mm, the comment should be changed. :-)

Fair enough. I guess Johannes will change that in the next post.
-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
  2012-07-09 20:37       ` Hugh Dickins
@ 2012-07-10 17:16         ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-10 17:16 UTC (permalink / raw)
  To: Hugh Dickins
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki,
	David Rientjes, linux-mm, cgroups, linux-kernel

On Mon 09-07-12 13:37:39, Hugh Dickins wrote:
> On Mon, 9 Jul 2012, Michal Hocko wrote:
> > 
> > Maybe I am missing something but who does the uncharge from:
> > shmem_unuse
> >   mem_cgroup_cache_charge
> >   shmem_unuse_inode
> >     shmem_add_to_page_cache
> 
> There isn't any special uncharge for shmem_unuse(): once the swapcache
> page is matched up with its memcg, it will get uncharged by one of the
> usual routes to swapcache_free() when the page is freed: maybe in the
> call from __remove_mapping(), maybe when free_page_and_swap_cache()
> ends up calling it.
> 
> Perhaps you're worrying about error (or unfound) paths in shmem_unuse()?

Yes that was exactly my concern.

> By the time we make the charge, we know for sure that it's a shmem page,
> and make the charge appropriately; in racy cases it might get uncharged
> again in the delete_from_swap_cache().  Can the unfound case occur these
> days?  

I cannot find a change that would prevent from that.

> I'd have to think more deeply to answer that, but the charge will
> not go missing.
> 
> Hugh

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
@ 2012-07-10 17:16         ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-10 17:16 UTC (permalink / raw)
  To: Hugh Dickins
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki,
	David Rientjes, linux-mm, cgroups, linux-kernel

On Mon 09-07-12 13:37:39, Hugh Dickins wrote:
> On Mon, 9 Jul 2012, Michal Hocko wrote:
> > 
> > Maybe I am missing something but who does the uncharge from:
> > shmem_unuse
> >   mem_cgroup_cache_charge
> >   shmem_unuse_inode
> >     shmem_add_to_page_cache
> 
> There isn't any special uncharge for shmem_unuse(): once the swapcache
> page is matched up with its memcg, it will get uncharged by one of the
> usual routes to swapcache_free() when the page is freed: maybe in the
> call from __remove_mapping(), maybe when free_page_and_swap_cache()
> ends up calling it.
> 
> Perhaps you're worrying about error (or unfound) paths in shmem_unuse()?

Yes that was exactly my concern.

> By the time we make the charge, we know for sure that it's a shmem page,
> and make the charge appropriately; in racy cases it might get uncharged
> again in the delete_from_swap_cache().  Can the unfound case occur these
> days?  

I cannot find a change that would prevent from that.

> I'd have to think more deeply to answer that, but the charge will
> not go missing.
> 
> Hugh

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
  2012-07-10 17:16         ` Michal Hocko
@ 2012-07-11 18:48           ` Hugh Dickins
  -1 siblings, 0 replies; 90+ messages in thread
From: Hugh Dickins @ 2012-07-11 18:48 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki,
	David Rientjes, linux-mm, cgroups, linux-kernel

On Tue, 10 Jul 2012, Michal Hocko wrote:
> On Mon 09-07-12 13:37:39, Hugh Dickins wrote:
> > On Mon, 9 Jul 2012, Michal Hocko wrote:
> > > 
> > > Maybe I am missing something but who does the uncharge from:
> > > shmem_unuse
> > >   mem_cgroup_cache_charge
> > >   shmem_unuse_inode
> > >     shmem_add_to_page_cache
> > 
> > There isn't any special uncharge for shmem_unuse(): once the swapcache
> > page is matched up with its memcg, it will get uncharged by one of the
> > usual routes to swapcache_free() when the page is freed: maybe in the
> > call from __remove_mapping(), maybe when free_page_and_swap_cache()
> > ends up calling it.
> > 
> > Perhaps you're worrying about error (or unfound) paths in shmem_unuse()?
> 
> Yes that was exactly my concern.
> 
> > By the time we make the charge, we know for sure that it's a shmem page,
> > and make the charge appropriately; in racy cases it might get uncharged
> > again in the delete_from_swap_cache().  Can the unfound case occur these
> > days?  
> 
> I cannot find a change that would prevent from that.

Yes.

> 
> > I'd have to think more deeply to answer that, but the charge will
> > not go missing.

Yes, the unfound case certainly can still occur these days.  It's very
similar to the race with truncation/eviction which shmem_unuse_inode()
already allows for (-ENOENT from shmem_add_to_page_cache()).  In that
"error" case, the swap entry got removed after we found it in the
file's radix tree, before we get to replace it there.  Whereas in the
"unfound" case, the swap entry got removed from the file's radix tree
before we even found it there, so we haven't a clue which file it ever
belonged to.

But it doesn't matter.  We have charged the memcg (the original memcg if
memsw is enabled, or swapoff's own if memsw is disabled), and the charge
is redundant now that the page has been truncated; but it's a common
occurrence with swapcache (most common while PageWriteback or PageLocked)
that the swap and charge cannot be released immediately, and it sorts
itself out under pressure once the page reaches the bottom of the
inactive anon and __remove_mapping()'s swapcache_free().

The worst of it is misleading stats meanwhile; but SwapCache has
always been tiresome that way (duplicated in memory and on swap).

The crucial change with regard to unfound entries was back in 2.6.33,
when we added SWAP_MAP_SHMEM: prior to that, we didn't know in advance
if the swap belonged to shmem or to task, and had to be more careful
about when we charge.

Hugh

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
@ 2012-07-11 18:48           ` Hugh Dickins
  0 siblings, 0 replies; 90+ messages in thread
From: Hugh Dickins @ 2012-07-11 18:48 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki,
	David Rientjes, linux-mm, cgroups, linux-kernel

On Tue, 10 Jul 2012, Michal Hocko wrote:
> On Mon 09-07-12 13:37:39, Hugh Dickins wrote:
> > On Mon, 9 Jul 2012, Michal Hocko wrote:
> > > 
> > > Maybe I am missing something but who does the uncharge from:
> > > shmem_unuse
> > >   mem_cgroup_cache_charge
> > >   shmem_unuse_inode
> > >     shmem_add_to_page_cache
> > 
> > There isn't any special uncharge for shmem_unuse(): once the swapcache
> > page is matched up with its memcg, it will get uncharged by one of the
> > usual routes to swapcache_free() when the page is freed: maybe in the
> > call from __remove_mapping(), maybe when free_page_and_swap_cache()
> > ends up calling it.
> > 
> > Perhaps you're worrying about error (or unfound) paths in shmem_unuse()?
> 
> Yes that was exactly my concern.
> 
> > By the time we make the charge, we know for sure that it's a shmem page,
> > and make the charge appropriately; in racy cases it might get uncharged
> > again in the delete_from_swap_cache().  Can the unfound case occur these
> > days?  
> 
> I cannot find a change that would prevent from that.

Yes.

> 
> > I'd have to think more deeply to answer that, but the charge will
> > not go missing.

Yes, the unfound case certainly can still occur these days.  It's very
similar to the race with truncation/eviction which shmem_unuse_inode()
already allows for (-ENOENT from shmem_add_to_page_cache()).  In that
"error" case, the swap entry got removed after we found it in the
file's radix tree, before we get to replace it there.  Whereas in the
"unfound" case, the swap entry got removed from the file's radix tree
before we even found it there, so we haven't a clue which file it ever
belonged to.

But it doesn't matter.  We have charged the memcg (the original memcg if
memsw is enabled, or swapoff's own if memsw is disabled), and the charge
is redundant now that the page has been truncated; but it's a common
occurrence with swapcache (most common while PageWriteback or PageLocked)
that the swap and charge cannot be released immediately, and it sorts
itself out under pressure once the page reaches the bottom of the
inactive anon and __remove_mapping()'s swapcache_free().

The worst of it is misleading stats meanwhile; but SwapCache has
always been tiresome that way (duplicated in memory and on swap).

The crucial change with regard to unfound entries was back in 2.6.33,
when we added SWAP_MAP_SHMEM: prior to that, we didn't know in advance
if the swap belonged to shmem or to task, and had to be more careful
about when we charge.

Hugh

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
  2012-07-11 18:48           ` Hugh Dickins
@ 2012-07-12 13:51             ` Michal Hocko
  -1 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-12 13:51 UTC (permalink / raw)
  To: Hugh Dickins
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki,
	David Rientjes, linux-mm, cgroups, linux-kernel

On Wed 11-07-12 11:48:54, Hugh Dickins wrote:
> On Tue, 10 Jul 2012, Michal Hocko wrote:
> > On Mon 09-07-12 13:37:39, Hugh Dickins wrote:
> > > On Mon, 9 Jul 2012, Michal Hocko wrote:
> > > > 
> > > > Maybe I am missing something but who does the uncharge from:
> > > > shmem_unuse
> > > >   mem_cgroup_cache_charge
> > > >   shmem_unuse_inode
> > > >     shmem_add_to_page_cache
> > > 
> > > There isn't any special uncharge for shmem_unuse(): once the swapcache
> > > page is matched up with its memcg, it will get uncharged by one of the
> > > usual routes to swapcache_free() when the page is freed: maybe in the
> > > call from __remove_mapping(), maybe when free_page_and_swap_cache()
> > > ends up calling it.
> > > 
> > > Perhaps you're worrying about error (or unfound) paths in shmem_unuse()?
> > 
> > Yes that was exactly my concern.
> > 
> > > By the time we make the charge, we know for sure that it's a shmem page,
> > > and make the charge appropriately; in racy cases it might get uncharged
> > > again in the delete_from_swap_cache().  Can the unfound case occur these
> > > days?  
> > 
> > I cannot find a change that would prevent from that.
> 
> Yes.
> 
> > 
> > > I'd have to think more deeply to answer that, but the charge will
> > > not go missing.
> 
> Yes, the unfound case certainly can still occur these days.  It's very
> similar to the race with truncation/eviction which shmem_unuse_inode()
> already allows for (-ENOENT from shmem_add_to_page_cache()).  In that
> "error" case, the swap entry got removed after we found it in the
> file's radix tree, before we get to replace it there.  Whereas in the
> "unfound" case, the swap entry got removed from the file's radix tree
> before we even found it there, so we haven't a clue which file it ever
> belonged to.
> 
> But it doesn't matter.  We have charged the memcg (the original memcg if
> memsw is enabled, or swapoff's own if memsw is disabled), and the charge
> is redundant now that the page has been truncated; but it's a common
> occurrence with swapcache (most common while PageWriteback or PageLocked)
> that the swap and charge cannot be released immediately, and it sorts
> itself out under pressure once the page reaches the bottom of the
> inactive anon and __remove_mapping()'s swapcache_free().
> 
> The worst of it is misleading stats meanwhile; but SwapCache has
> always been tiresome that way (duplicated in memory and on swap).

Indeed

> 
> The crucial change with regard to unfound entries was back in 2.6.33,
> when we added SWAP_MAP_SHMEM: prior to that, we didn't know in advance
> if the swap belonged to shmem or to task, and had to be more careful
> about when we charge.

Thanks a lot for the clarification Hugh! The code is really tricky and
easy to get wrong.

> 
> Hugh

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

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages
@ 2012-07-12 13:51             ` Michal Hocko
  0 siblings, 0 replies; 90+ messages in thread
From: Michal Hocko @ 2012-07-12 13:51 UTC (permalink / raw)
  To: Hugh Dickins
  Cc: Johannes Weiner, Andrew Morton, KAMEZAWA Hiroyuki,
	David Rientjes, linux-mm, cgroups, linux-kernel

On Wed 11-07-12 11:48:54, Hugh Dickins wrote:
> On Tue, 10 Jul 2012, Michal Hocko wrote:
> > On Mon 09-07-12 13:37:39, Hugh Dickins wrote:
> > > On Mon, 9 Jul 2012, Michal Hocko wrote:
> > > > 
> > > > Maybe I am missing something but who does the uncharge from:
> > > > shmem_unuse
> > > >   mem_cgroup_cache_charge
> > > >   shmem_unuse_inode
> > > >     shmem_add_to_page_cache
> > > 
> > > There isn't any special uncharge for shmem_unuse(): once the swapcache
> > > page is matched up with its memcg, it will get uncharged by one of the
> > > usual routes to swapcache_free() when the page is freed: maybe in the
> > > call from __remove_mapping(), maybe when free_page_and_swap_cache()
> > > ends up calling it.
> > > 
> > > Perhaps you're worrying about error (or unfound) paths in shmem_unuse()?
> > 
> > Yes that was exactly my concern.
> > 
> > > By the time we make the charge, we know for sure that it's a shmem page,
> > > and make the charge appropriately; in racy cases it might get uncharged
> > > again in the delete_from_swap_cache().  Can the unfound case occur these
> > > days?  
> > 
> > I cannot find a change that would prevent from that.
> 
> Yes.
> 
> > 
> > > I'd have to think more deeply to answer that, but the charge will
> > > not go missing.
> 
> Yes, the unfound case certainly can still occur these days.  It's very
> similar to the race with truncation/eviction which shmem_unuse_inode()
> already allows for (-ENOENT from shmem_add_to_page_cache()).  In that
> "error" case, the swap entry got removed after we found it in the
> file's radix tree, before we get to replace it there.  Whereas in the
> "unfound" case, the swap entry got removed from the file's radix tree
> before we even found it there, so we haven't a clue which file it ever
> belonged to.
> 
> But it doesn't matter.  We have charged the memcg (the original memcg if
> memsw is enabled, or swapoff's own if memsw is disabled), and the charge
> is redundant now that the page has been truncated; but it's a common
> occurrence with swapcache (most common while PageWriteback or PageLocked)
> that the swap and charge cannot be released immediately, and it sorts
> itself out under pressure once the page reaches the bottom of the
> inactive anon and __remove_mapping()'s swapcache_free().
> 
> The worst of it is misleading stats meanwhile; but SwapCache has
> always been tiresome that way (duplicated in memory and on swap).

Indeed

> 
> The crucial change with regard to unfound entries was back in 2.6.33,
> when we added SWAP_MAP_SHMEM: prior to that, we didn't know in advance
> if the swap belonged to shmem or to task, and had to be more careful
> about when we charge.

Thanks a lot for the clarification Hugh! The code is really tricky and
easy to get wrong.

> 
> Hugh

-- 
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 majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 90+ messages in thread

end of thread, other threads:[~2012-07-12 13:51 UTC | newest]

Thread overview: 90+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-05  0:44 [patch 00/11] mm: memcg: charge/uncharge improvements Johannes Weiner
2012-07-05  0:44 ` Johannes Weiner
2012-07-05  0:44 ` [patch 01/11] mm: memcg: fix compaction/migration failing due to memcg limits Johannes Weiner
2012-07-05  0:44   ` Johannes Weiner
2012-07-09  2:27   ` Kamezawa Hiroyuki
2012-07-09  2:27     ` Kamezawa Hiroyuki
2012-07-09 14:15   ` Michal Hocko
2012-07-09 14:15     ` Michal Hocko
2012-07-05  0:44 ` [patch 02/11] mm: swapfile: clean up unuse_pte race handling Johannes Weiner
2012-07-05  0:44   ` Johannes Weiner
2012-07-09  2:29   ` Kamezawa Hiroyuki
2012-07-09  2:29     ` Kamezawa Hiroyuki
2012-07-09 14:22   ` Michal Hocko
2012-07-09 14:22     ` Michal Hocko
2012-07-05  0:44 ` [patch 03/11] mm: shmem: do not try to uncharge known swapcache pages Johannes Weiner
2012-07-05  0:44   ` Johannes Weiner
2012-07-09  2:33   ` Kamezawa Hiroyuki
2012-07-09  2:33     ` Kamezawa Hiroyuki
2012-07-09 14:46   ` Michal Hocko
2012-07-09 14:46     ` Michal Hocko
2012-07-09 20:37     ` Hugh Dickins
2012-07-09 20:37       ` Hugh Dickins
2012-07-10 17:16       ` Michal Hocko
2012-07-10 17:16         ` Michal Hocko
2012-07-11 18:48         ` Hugh Dickins
2012-07-11 18:48           ` Hugh Dickins
2012-07-12 13:51           ` Michal Hocko
2012-07-12 13:51             ` Michal Hocko
2012-07-09 20:11   ` Hugh Dickins
2012-07-09 20:11     ` Hugh Dickins
2012-07-05  0:44 ` [patch 04/11] mm: memcg: push down PageSwapCache check into uncharge entry functions Johannes Weiner
2012-07-05  0:44   ` Johannes Weiner
2012-07-09  2:42   ` Kamezawa Hiroyuki
2012-07-09  2:42     ` Kamezawa Hiroyuki
2012-07-09  7:36     ` Johannes Weiner
2012-07-09  7:36       ` Johannes Weiner
2012-07-09 15:02   ` Michal Hocko
2012-07-09 15:02     ` Michal Hocko
2012-07-05  0:44 ` [patch 05/11] mm: memcg: only check for PageSwapCache when uncharging anon Johannes Weiner
2012-07-05  0:44   ` Johannes Weiner
2012-07-09  2:49   ` Kamezawa Hiroyuki
2012-07-09  2:49     ` Kamezawa Hiroyuki
2012-07-09 15:05   ` Michal Hocko
2012-07-09 15:05     ` Michal Hocko
2012-07-05  0:44 ` [patch 06/11] mm: memcg: move swapin charge functions above callsites Johannes Weiner
2012-07-05  0:44   ` Johannes Weiner
2012-07-09  2:50   ` Kamezawa Hiroyuki
2012-07-09  2:50     ` Kamezawa Hiroyuki
2012-07-09 15:10   ` Michal Hocko
2012-07-09 15:10     ` Michal Hocko
2012-07-05  0:44 ` [patch 07/11] mm: memcg: remove unneeded shmem charge type Johannes Weiner
2012-07-05  0:44   ` Johannes Weiner
2012-07-09  2:51   ` Kamezawa Hiroyuki
2012-07-09  2:51     ` Kamezawa Hiroyuki
2012-07-09 15:17   ` Michal Hocko
2012-07-09 15:17     ` Michal Hocko
2012-07-05  0:45 ` [patch 08/11] mm: memcg: remove needless !mm fixup to init_mm when charging Johannes Weiner
2012-07-05  0:45   ` Johannes Weiner
2012-07-09  2:53   ` Kamezawa Hiroyuki
2012-07-09  2:53     ` Kamezawa Hiroyuki
2012-07-09 15:20   ` Michal Hocko
2012-07-09 15:20     ` Michal Hocko
2012-07-10  6:10     ` Wanpeng Li
2012-07-10  6:10       ` Wanpeng Li
2012-07-10  6:21       ` Michal Hocko
2012-07-10  6:21         ` Michal Hocko
2012-07-10  6:54         ` Wanpeng Li
2012-07-10  6:54           ` Wanpeng Li
2012-07-10 16:22           ` Michal Hocko
2012-07-10 16:22             ` Michal Hocko
2012-07-05  0:45 ` [patch 09/11] mm: memcg: split swapin charge function into private and public part Johannes Weiner
2012-07-05  0:45   ` Johannes Weiner
2012-07-09  2:55   ` Kamezawa Hiroyuki
2012-07-09  2:55     ` Kamezawa Hiroyuki
2012-07-09 15:28   ` Michal Hocko
2012-07-09 15:28     ` Michal Hocko
2012-07-05  0:45 ` [patch 10/11] mm: memcg: only check swap cache pages for repeated charging Johannes Weiner
2012-07-05  0:45   ` Johannes Weiner
2012-07-09  3:26   ` Kamezawa Hiroyuki
2012-07-09  3:26     ` Kamezawa Hiroyuki
2012-07-09 15:32   ` Michal Hocko
2012-07-09 15:32     ` Michal Hocko
2012-07-05  0:45 ` [patch 11/11] mm: memcg: only check anon swapin page charges for swap cache Johannes Weiner
2012-07-05  0:45   ` Johannes Weiner
2012-07-09  3:44   ` Kamezawa Hiroyuki
2012-07-09  3:44     ` Kamezawa Hiroyuki
2012-07-09 15:34   ` Michal Hocko
2012-07-09 15:34     ` Michal Hocko
2012-07-09 15:35 ` [patch 00/11] mm: memcg: charge/uncharge improvements Michal Hocko
2012-07-09 15:35   ` Michal Hocko

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.