Skip to content

Commit 9d82c69

Browse files
hnaztorvalds
authored andcommitted
mm: memcontrol: convert anon and file-thp to new mem_cgroup_charge() API
With the page->mapping requirement gone from memcg, we can charge anon and file-thp pages in one single step, right after they're allocated. This removes two out of three API calls - especially the tricky commit step that needed to happen at just the right time between when the page is "set up" and when it's "published" - somewhat vague and fluid concepts that varied by page type. All we need is a freshly allocated page and a memcg context to charge. v2: prevent double charges on pre-allocated hugepages in khugepaged [[email protected]: Fix crash - *hpage could be ERR_PTR instead of NULL] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Johannes Weiner <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Reviewed-by: Joonsoo Kim <[email protected]> Cc: Alex Shi <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: "Kirill A. Shutemov" <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Roman Gushchin <[email protected]> Cc: Shakeel Butt <[email protected]> Cc: Balbir Singh <[email protected]> Cc: Qian Cai <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Linus Torvalds <[email protected]>
1 parent 468c398 commit 9d82c69

File tree

9 files changed

+31
-82
lines changed

9 files changed

+31
-82
lines changed

include/linux/mm.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,6 @@ struct vm_fault {
501501
pte_t orig_pte; /* Value of PTE at the time of fault */
502502

503503
struct page *cow_page; /* Page handler may use for COW fault */
504-
struct mem_cgroup *memcg; /* Cgroup cow_page belongs to */
505504
struct page *page; /* ->fault handlers should return a
506505
* page here, unless VM_FAULT_NOPAGE
507506
* is set (which is also implied by
@@ -946,8 +945,7 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
946945
return pte;
947946
}
948947

949-
vm_fault_t alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
950-
struct page *page);
948+
vm_fault_t alloc_set_pte(struct vm_fault *vmf, struct page *page);
951949
vm_fault_t finish_fault(struct vm_fault *vmf);
952950
vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf);
953951
#endif

kernel/events/uprobes.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,14 +162,13 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
162162
};
163163
int err;
164164
struct mmu_notifier_range range;
165-
struct mem_cgroup *memcg;
166165

167166
mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, mm, addr,
168167
addr + PAGE_SIZE);
169168

170169
if (new_page) {
171-
err = mem_cgroup_try_charge(new_page, vma->vm_mm, GFP_KERNEL,
172-
&memcg);
170+
err = mem_cgroup_charge(new_page, vma->vm_mm, GFP_KERNEL,
171+
false);
173172
if (err)
174173
return err;
175174
}
@@ -179,16 +178,12 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
179178

180179
mmu_notifier_invalidate_range_start(&range);
181180
err = -EAGAIN;
182-
if (!page_vma_mapped_walk(&pvmw)) {
183-
if (new_page)
184-
mem_cgroup_cancel_charge(new_page, memcg);
181+
if (!page_vma_mapped_walk(&pvmw))
185182
goto unlock;
186-
}
187183
VM_BUG_ON_PAGE(addr != pvmw.address, old_page);
188184

189185
if (new_page) {
190186
get_page(new_page);
191-
mem_cgroup_commit_charge(new_page, memcg, false);
192187
page_add_new_anon_rmap(new_page, vma, addr, false);
193188
lru_cache_add_active_or_unevictable(new_page, vma);
194189
} else

mm/filemap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2633,7 +2633,7 @@ void filemap_map_pages(struct vm_fault *vmf,
26332633
if (vmf->pte)
26342634
vmf->pte += xas.xa_index - last_pgoff;
26352635
last_pgoff = xas.xa_index;
2636-
if (alloc_set_pte(vmf, NULL, page))
2636+
if (alloc_set_pte(vmf, page))
26372637
goto unlock;
26382638
unlock_page(page);
26392639
goto next;

mm/huge_memory.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -587,19 +587,19 @@ static vm_fault_t __do_huge_pmd_anonymous_page(struct vm_fault *vmf,
587587
struct page *page, gfp_t gfp)
588588
{
589589
struct vm_area_struct *vma = vmf->vma;
590-
struct mem_cgroup *memcg;
591590
pgtable_t pgtable;
592591
unsigned long haddr = vmf->address & HPAGE_PMD_MASK;
593592
vm_fault_t ret = 0;
594593

595594
VM_BUG_ON_PAGE(!PageCompound(page), page);
596595

597-
if (mem_cgroup_try_charge_delay(page, vma->vm_mm, gfp, &memcg)) {
596+
if (mem_cgroup_charge(page, vma->vm_mm, gfp, false)) {
598597
put_page(page);
599598
count_vm_event(THP_FAULT_FALLBACK);
600599
count_vm_event(THP_FAULT_FALLBACK_CHARGE);
601600
return VM_FAULT_FALLBACK;
602601
}
602+
cgroup_throttle_swaprate(page, gfp);
603603

604604
pgtable = pte_alloc_one(vma->vm_mm);
605605
if (unlikely(!pgtable)) {
@@ -630,7 +630,6 @@ static vm_fault_t __do_huge_pmd_anonymous_page(struct vm_fault *vmf,
630630
vm_fault_t ret2;
631631

632632
spin_unlock(vmf->ptl);
633-
mem_cgroup_cancel_charge(page, memcg);
634633
put_page(page);
635634
pte_free(vma->vm_mm, pgtable);
636635
ret2 = handle_userfault(vmf, VM_UFFD_MISSING);
@@ -640,7 +639,6 @@ static vm_fault_t __do_huge_pmd_anonymous_page(struct vm_fault *vmf,
640639

641640
entry = mk_huge_pmd(page, vma->vm_page_prot);
642641
entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
643-
mem_cgroup_commit_charge(page, memcg, false);
644642
page_add_new_anon_rmap(page, vma, haddr, true);
645643
lru_cache_add_active_or_unevictable(page, vma);
646644
pgtable_trans_huge_deposit(vma->vm_mm, vmf->pmd, pgtable);
@@ -649,7 +647,7 @@ static vm_fault_t __do_huge_pmd_anonymous_page(struct vm_fault *vmf,
649647
mm_inc_nr_ptes(vma->vm_mm);
650648
spin_unlock(vmf->ptl);
651649
count_vm_event(THP_FAULT_ALLOC);
652-
count_memcg_events(memcg, THP_FAULT_ALLOC, 1);
650+
count_memcg_event_mm(vma->vm_mm, THP_FAULT_ALLOC);
653651
}
654652

655653
return 0;
@@ -658,7 +656,6 @@ static vm_fault_t __do_huge_pmd_anonymous_page(struct vm_fault *vmf,
658656
release:
659657
if (pgtable)
660658
pte_free(vma->vm_mm, pgtable);
661-
mem_cgroup_cancel_charge(page, memcg);
662659
put_page(page);
663660
return ret;
664661

mm/khugepaged.c

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,6 @@ static void collapse_huge_page(struct mm_struct *mm,
10371037
struct page *new_page;
10381038
spinlock_t *pmd_ptl, *pte_ptl;
10391039
int isolated = 0, result = 0;
1040-
struct mem_cgroup *memcg;
10411040
struct vm_area_struct *vma;
10421041
struct mmu_notifier_range range;
10431042
gfp_t gfp;
@@ -1060,23 +1059,22 @@ static void collapse_huge_page(struct mm_struct *mm,
10601059
goto out_nolock;
10611060
}
10621061

1063-
if (unlikely(mem_cgroup_try_charge(new_page, mm, gfp, &memcg))) {
1062+
if (unlikely(mem_cgroup_charge(new_page, mm, gfp, false))) {
10641063
result = SCAN_CGROUP_CHARGE_FAIL;
10651064
goto out_nolock;
10661065
}
1066+
count_memcg_page_event(new_page, THP_COLLAPSE_ALLOC);
10671067

10681068
down_read(&mm->mmap_sem);
10691069
result = hugepage_vma_revalidate(mm, address, &vma);
10701070
if (result) {
1071-
mem_cgroup_cancel_charge(new_page, memcg);
10721071
up_read(&mm->mmap_sem);
10731072
goto out_nolock;
10741073
}
10751074

10761075
pmd = mm_find_pmd(mm, address);
10771076
if (!pmd) {
10781077
result = SCAN_PMD_NULL;
1079-
mem_cgroup_cancel_charge(new_page, memcg);
10801078
up_read(&mm->mmap_sem);
10811079
goto out_nolock;
10821080
}
@@ -1088,7 +1086,6 @@ static void collapse_huge_page(struct mm_struct *mm,
10881086
*/
10891087
if (unmapped && !__collapse_huge_page_swapin(mm, vma, address,
10901088
pmd, referenced)) {
1091-
mem_cgroup_cancel_charge(new_page, memcg);
10921089
up_read(&mm->mmap_sem);
10931090
goto out_nolock;
10941091
}
@@ -1175,9 +1172,7 @@ static void collapse_huge_page(struct mm_struct *mm,
11751172

11761173
spin_lock(pmd_ptl);
11771174
BUG_ON(!pmd_none(*pmd));
1178-
mem_cgroup_commit_charge(new_page, memcg, false);
11791175
page_add_new_anon_rmap(new_page, vma, address, true);
1180-
count_memcg_events(memcg, THP_COLLAPSE_ALLOC, 1);
11811176
lru_cache_add_active_or_unevictable(new_page, vma);
11821177
pgtable_trans_huge_deposit(mm, pmd, pgtable);
11831178
set_pmd_at(mm, address, pmd, _pmd);
@@ -1191,10 +1186,11 @@ static void collapse_huge_page(struct mm_struct *mm,
11911186
out_up_write:
11921187
up_write(&mm->mmap_sem);
11931188
out_nolock:
1189+
if (!IS_ERR_OR_NULL(*hpage))
1190+
mem_cgroup_uncharge(*hpage);
11941191
trace_mm_collapse_huge_page(mm, isolated, result);
11951192
return;
11961193
out:
1197-
mem_cgroup_cancel_charge(new_page, memcg);
11981194
goto out_up_write;
11991195
}
12001196

@@ -1618,7 +1614,6 @@ static void collapse_file(struct mm_struct *mm,
16181614
struct address_space *mapping = file->f_mapping;
16191615
gfp_t gfp;
16201616
struct page *new_page;
1621-
struct mem_cgroup *memcg;
16221617
pgoff_t index, end = start + HPAGE_PMD_NR;
16231618
LIST_HEAD(pagelist);
16241619
XA_STATE_ORDER(xas, &mapping->i_pages, start, HPAGE_PMD_ORDER);
@@ -1637,10 +1632,11 @@ static void collapse_file(struct mm_struct *mm,
16371632
goto out;
16381633
}
16391634

1640-
if (unlikely(mem_cgroup_try_charge(new_page, mm, gfp, &memcg))) {
1635+
if (unlikely(mem_cgroup_charge(new_page, mm, gfp, false))) {
16411636
result = SCAN_CGROUP_CHARGE_FAIL;
16421637
goto out;
16431638
}
1639+
count_memcg_page_event(new_page, THP_COLLAPSE_ALLOC);
16441640

16451641
/* This will be less messy when we use multi-index entries */
16461642
do {
@@ -1650,7 +1646,6 @@ static void collapse_file(struct mm_struct *mm,
16501646
break;
16511647
xas_unlock_irq(&xas);
16521648
if (!xas_nomem(&xas, GFP_KERNEL)) {
1653-
mem_cgroup_cancel_charge(new_page, memcg);
16541649
result = SCAN_FAIL;
16551650
goto out;
16561651
}
@@ -1844,18 +1839,9 @@ static void collapse_file(struct mm_struct *mm,
18441839
}
18451840

18461841
if (nr_none) {
1847-
struct lruvec *lruvec;
1848-
/*
1849-
* XXX: We have started try_charge and pinned the
1850-
* memcg, but the page isn't committed yet so we
1851-
* cannot use mod_lruvec_page_state(). This hackery
1852-
* will be cleaned up when remove the page->mapping
1853-
* dependency from memcg and fully charge above.
1854-
*/
1855-
lruvec = mem_cgroup_lruvec(memcg, page_pgdat(new_page));
1856-
__mod_lruvec_state(lruvec, NR_FILE_PAGES, nr_none);
1842+
__mod_lruvec_page_state(new_page, NR_FILE_PAGES, nr_none);
18571843
if (is_shmem)
1858-
__mod_lruvec_state(lruvec, NR_SHMEM, nr_none);
1844+
__mod_lruvec_page_state(new_page, NR_SHMEM, nr_none);
18591845
}
18601846

18611847
xa_locked:
@@ -1893,15 +1879,13 @@ static void collapse_file(struct mm_struct *mm,
18931879

18941880
SetPageUptodate(new_page);
18951881
page_ref_add(new_page, HPAGE_PMD_NR - 1);
1896-
mem_cgroup_commit_charge(new_page, memcg, false);
18971882

18981883
if (is_shmem) {
18991884
set_page_dirty(new_page);
19001885
lru_cache_add_anon(new_page);
19011886
} else {
19021887
lru_cache_add_file(new_page);
19031888
}
1904-
count_memcg_events(memcg, THP_COLLAPSE_ALLOC, 1);
19051889

19061890
/*
19071891
* Remove pte page tables, so we can re-fault the page as huge.
@@ -1948,13 +1932,14 @@ static void collapse_file(struct mm_struct *mm,
19481932
VM_BUG_ON(nr_none);
19491933
xas_unlock_irq(&xas);
19501934

1951-
mem_cgroup_cancel_charge(new_page, memcg);
19521935
new_page->mapping = NULL;
19531936
}
19541937

19551938
unlock_page(new_page);
19561939
out:
19571940
VM_BUG_ON(!list_empty(&pagelist));
1941+
if (!IS_ERR_OR_NULL(*hpage))
1942+
mem_cgroup_uncharge(*hpage);
19581943
/* TODO: tracepoints */
19591944
}
19601945

0 commit comments

Comments
 (0)