aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c52
1 files changed, 35 insertions, 17 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 356d4964fe95..a1bb59d4c9d0 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2094,23 +2094,10 @@ struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
2094 * commit a charge got by __mem_cgroup_try_charge() and makes page_cgroup to be 2094 * commit a charge got by __mem_cgroup_try_charge() and makes page_cgroup to be
2095 * USED state. If already USED, uncharge and return. 2095 * USED state. If already USED, uncharge and return.
2096 */ 2096 */
2097 2097static void ____mem_cgroup_commit_charge(struct mem_cgroup *mem,
2098static void __mem_cgroup_commit_charge(struct mem_cgroup *mem, 2098 struct page_cgroup *pc,
2099 struct page_cgroup *pc, 2099 enum charge_type ctype)
2100 enum charge_type ctype,
2101 int page_size)
2102{ 2100{
2103 /* try_charge() can return NULL to *memcg, taking care of it. */
2104 if (!mem)
2105 return;
2106
2107 lock_page_cgroup(pc);
2108 if (unlikely(PageCgroupUsed(pc))) {
2109 unlock_page_cgroup(pc);
2110 mem_cgroup_cancel_charge(mem, page_size);
2111 return;
2112 }
2113
2114 pc->mem_cgroup = mem; 2101 pc->mem_cgroup = mem;
2115 /* 2102 /*
2116 * We access a page_cgroup asynchronously without lock_page_cgroup(). 2103 * We access a page_cgroup asynchronously without lock_page_cgroup().
@@ -2135,6 +2122,33 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
2135 } 2122 }
2136 2123
2137 mem_cgroup_charge_statistics(mem, pc, true); 2124 mem_cgroup_charge_statistics(mem, pc, true);
2125}
2126
2127static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
2128 struct page_cgroup *pc,
2129 enum charge_type ctype,
2130 int page_size)
2131{
2132 int i;
2133 int count = page_size >> PAGE_SHIFT;
2134
2135 /* try_charge() can return NULL to *memcg, taking care of it. */
2136 if (!mem)
2137 return;
2138
2139 lock_page_cgroup(pc);
2140 if (unlikely(PageCgroupUsed(pc))) {
2141 unlock_page_cgroup(pc);
2142 mem_cgroup_cancel_charge(mem, page_size);
2143 return;
2144 }
2145
2146 /*
2147 * we don't need page_cgroup_lock about tail pages, becase they are not
2148 * accessed by any other context at this point.
2149 */
2150 for (i = 0; i < count; i++)
2151 ____mem_cgroup_commit_charge(mem, pc + i, ctype);
2138 2152
2139 unlock_page_cgroup(pc); 2153 unlock_page_cgroup(pc);
2140 /* 2154 /*
@@ -2532,6 +2546,8 @@ direct_uncharge:
2532static struct mem_cgroup * 2546static struct mem_cgroup *
2533__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype) 2547__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
2534{ 2548{
2549 int i;
2550 int count;
2535 struct page_cgroup *pc; 2551 struct page_cgroup *pc;
2536 struct mem_cgroup *mem = NULL; 2552 struct mem_cgroup *mem = NULL;
2537 int page_size = PAGE_SIZE; 2553 int page_size = PAGE_SIZE;
@@ -2545,6 +2561,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
2545 if (PageTransHuge(page)) 2561 if (PageTransHuge(page))
2546 page_size <<= compound_order(page); 2562 page_size <<= compound_order(page);
2547 2563
2564 count = page_size >> PAGE_SHIFT;
2548 /* 2565 /*
2549 * Check if our page_cgroup is valid 2566 * Check if our page_cgroup is valid
2550 */ 2567 */
@@ -2577,7 +2594,8 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
2577 break; 2594 break;
2578 } 2595 }
2579 2596
2580 mem_cgroup_charge_statistics(mem, pc, false); 2597 for (i = 0; i < count; i++)
2598 mem_cgroup_charge_statistics(mem, pc + i, false);
2581 2599
2582 ClearPageCgroupUsed(pc); 2600 ClearPageCgroupUsed(pc);
2583 /* 2601 /*