aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/memcontrol.h5
-rw-r--r--mm/huge_memory.c3
-rw-r--r--mm/memcontrol.c34
3 files changed, 21 insertions, 21 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index e2f8e7caf04b..cee3761666f0 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -163,7 +163,7 @@ u64 mem_cgroup_get_limit(struct mem_cgroup *memcg);
163 163
164void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx); 164void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx);
165#ifdef CONFIG_TRANSPARENT_HUGEPAGE 165#ifdef CONFIG_TRANSPARENT_HUGEPAGE
166void mem_cgroup_split_huge_fixup(struct page *head, struct page *tail); 166void mem_cgroup_split_huge_fixup(struct page *head);
167#endif 167#endif
168 168
169#ifdef CONFIG_DEBUG_VM 169#ifdef CONFIG_DEBUG_VM
@@ -379,8 +379,7 @@ u64 mem_cgroup_get_limit(struct mem_cgroup *memcg)
379 return 0; 379 return 0;
380} 380}
381 381
382static inline void mem_cgroup_split_huge_fixup(struct page *head, 382static inline void mem_cgroup_split_huge_fixup(struct page *head)
383 struct page *tail)
384{ 383{
385} 384}
386 385
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 36b3d988b4ef..db522e160cca 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1207,6 +1207,8 @@ static void __split_huge_page_refcount(struct page *page)
1207 /* prevent PageLRU to go away from under us, and freeze lru stats */ 1207 /* prevent PageLRU to go away from under us, and freeze lru stats */
1208 spin_lock_irq(&zone->lru_lock); 1208 spin_lock_irq(&zone->lru_lock);
1209 compound_lock(page); 1209 compound_lock(page);
1210 /* complete memcg works before add pages to LRU */
1211 mem_cgroup_split_huge_fixup(page);
1210 1212
1211 for (i = 1; i < HPAGE_PMD_NR; i++) { 1213 for (i = 1; i < HPAGE_PMD_NR; i++) {
1212 struct page *page_tail = page + i; 1214 struct page *page_tail = page + i;
@@ -1278,7 +1280,6 @@ static void __split_huge_page_refcount(struct page *page)
1278 BUG_ON(!PageDirty(page_tail)); 1280 BUG_ON(!PageDirty(page_tail));
1279 BUG_ON(!PageSwapBacked(page_tail)); 1281 BUG_ON(!PageSwapBacked(page_tail));
1280 1282
1281 mem_cgroup_split_huge_fixup(page, page_tail);
1282 1283
1283 lru_add_page_tail(zone, page, page_tail); 1284 lru_add_page_tail(zone, page, page_tail);
1284 } 1285 }
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 972878b648c2..42174612cc0b 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2553,39 +2553,39 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
2553 (1 << PCG_ACCT_LRU) | (1 << PCG_MIGRATION)) 2553 (1 << PCG_ACCT_LRU) | (1 << PCG_MIGRATION))
2554/* 2554/*
2555 * Because tail pages are not marked as "used", set it. We're under 2555 * Because tail pages are not marked as "used", set it. We're under
2556 * zone->lru_lock, 'splitting on pmd' and compund_lock. 2556 * zone->lru_lock, 'splitting on pmd' and compound_lock.
2557 * charge/uncharge will be never happen and move_account() is done under
2558 * compound_lock(), so we don't have to take care of races.
2557 */ 2559 */
2558void mem_cgroup_split_huge_fixup(struct page *head, struct page *tail) 2560void mem_cgroup_split_huge_fixup(struct page *head)
2559{ 2561{
2560 struct page_cgroup *head_pc = lookup_page_cgroup(head); 2562 struct page_cgroup *head_pc = lookup_page_cgroup(head);
2561 struct page_cgroup *tail_pc = lookup_page_cgroup(tail); 2563 struct page_cgroup *pc;
2562 unsigned long flags; 2564 int i;
2563 2565
2564 if (mem_cgroup_disabled()) 2566 if (mem_cgroup_disabled())
2565 return; 2567 return;
2566 /* 2568 for (i = 1; i < HPAGE_PMD_NR; i++) {
2567 * We have no races with charge/uncharge but will have races with 2569 pc = head_pc + i;
2568 * page state accounting. 2570 pc->mem_cgroup = head_pc->mem_cgroup;
2569 */ 2571 smp_wmb();/* see __commit_charge() */
2570 move_lock_page_cgroup(head_pc, &flags); 2572 /*
2573 * LRU flags cannot be copied because we need to add tail
2574 * page to LRU by generic call and our hooks will be called.
2575 */
2576 pc->flags = head_pc->flags & ~PCGF_NOCOPY_AT_SPLIT;
2577 }
2571 2578
2572 tail_pc->mem_cgroup = head_pc->mem_cgroup;
2573 smp_wmb(); /* see __commit_charge() */
2574 if (PageCgroupAcctLRU(head_pc)) { 2579 if (PageCgroupAcctLRU(head_pc)) {
2575 enum lru_list lru; 2580 enum lru_list lru;
2576 struct mem_cgroup_per_zone *mz; 2581 struct mem_cgroup_per_zone *mz;
2577
2578 /* 2582 /*
2579 * LRU flags cannot be copied because we need to add tail
2580 *.page to LRU by generic call and our hook will be called.
2581 * We hold lru_lock, then, reduce counter directly. 2583 * We hold lru_lock, then, reduce counter directly.
2582 */ 2584 */
2583 lru = page_lru(head); 2585 lru = page_lru(head);
2584 mz = page_cgroup_zoneinfo(head_pc->mem_cgroup, head); 2586 mz = page_cgroup_zoneinfo(head_pc->mem_cgroup, head);
2585 MEM_CGROUP_ZSTAT(mz, lru) -= 1; 2587 MEM_CGROUP_ZSTAT(mz, lru) -= HPAGE_PMD_NR - 1;
2586 } 2588 }
2587 tail_pc->flags = head_pc->flags & ~PCGF_NOCOPY_AT_SPLIT;
2588 move_unlock_page_cgroup(head_pc, &flags);
2589} 2589}
2590#endif 2590#endif
2591 2591