diff options
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r-- | mm/memcontrol.c | 52 |
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 | 2097 | static void ____mem_cgroup_commit_charge(struct mem_cgroup *mem, | |
2098 | static 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 | |||
2127 | static 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: | |||
2532 | static struct mem_cgroup * | 2546 | static 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 | /* |