@@ -5461,42 +5461,44 @@ static int mem_cgroup_do_precharge(unsigned long count)
}
union mc_target {
- struct page *page;
+ struct folio *folio;
swp_entry_t ent;
};
enum mc_target_type {
MC_TARGET_NONE = 0,
- MC_TARGET_PAGE,
+ MC_TARGET_FOLIO,
MC_TARGET_SWAP,
MC_TARGET_DEVICE,
};
-static struct page *mc_handle_present_pte(struct vm_area_struct *vma,
+static struct folio *mc_handle_present_pte(struct vm_area_struct *vma,
unsigned long addr, pte_t ptent)
{
struct page *page = vm_normal_page(vma, addr, ptent);
+ struct folio *folio;
if (!page || !page_mapped(page))
return NULL;
- if (PageAnon(page)) {
+ folio = page_folio(page);
+ if (folio_test_anon(folio)) {
if (!(mc.flags & MOVE_ANON))
return NULL;
} else {
if (!(mc.flags & MOVE_FILE))
return NULL;
}
- if (!get_page_unless_zero(page))
+ if (!folio_try_get(folio))
return NULL;
- return page;
+ return folio;
}
#if defined(CONFIG_SWAP) || defined(CONFIG_DEVICE_PRIVATE)
-static struct page *mc_handle_swap_pte(struct vm_area_struct *vma,
+static struct folio *mc_handle_swap_pte(struct vm_area_struct *vma,
pte_t ptent, swp_entry_t *entry)
{
- struct page *page = NULL;
+ struct folio *folio;
swp_entry_t ent = pte_to_swp_entry(ptent);
if (!(mc.flags & MOVE_ANON))
@@ -5507,10 +5509,12 @@ static struct page *mc_handle_swap_pte(struct vm_area_struct *vma,
* stored as special swap entries in the page table.
*/
if (is_device_private_entry(ent)) {
- page = pfn_swap_entry_to_page(ent);
- if (!get_page_unless_zero(page))
+ struct page *page = pfn_swap_entry_to_page(ent);
+
+ folio = page_folio(page);
+ if (!folio_try_get(folio))
return NULL;
- return page;
+ return folio;
}
if (non_swap_entry(ent))
@@ -5518,22 +5522,22 @@ static struct page *mc_handle_swap_pte(struct vm_area_struct *vma,
/*
* Because lookup_swap_cache() updates some statistics counter,
- * we call find_get_page() with swapper_space directly.
+ * we call filemap_get_folio() with swapper_space directly.
*/
- page = find_get_page(swap_address_space(ent), swp_offset(ent));
+ folio = filemap_get_folio(swap_address_space(ent), swp_offset(ent));
entry->val = ent.val;
- return page;
+ return folio;
}
#else
-static struct page *mc_handle_swap_pte(struct vm_area_struct *vma,
+static struct folio *mc_handle_swap_pte(struct vm_area_struct *vma,
pte_t ptent, swp_entry_t *entry)
{
return NULL;
}
#endif
-static struct page *mc_handle_file_pte(struct vm_area_struct *vma,
+static struct folio *mc_handle_file_pte(struct vm_area_struct *vma,
unsigned long addr, pte_t ptent)
{
if (!vma->vm_file) /* anonymous vma */
@@ -5543,28 +5547,28 @@ static struct page *mc_handle_file_pte(struct vm_area_struct *vma,
/* page is moved even if it's not RSS of this task(page-faulted). */
/* shmem/tmpfs may report page out on swap: account for that too. */
- return find_get_incore_page(vma->vm_file->f_mapping,
- linear_page_index(vma, addr));
+ return page_folio(find_get_incore_page(vma->vm_file->f_mapping,
+ linear_page_index(vma, addr)));
}
/**
- * mem_cgroup_move_account - move account of the page
- * @page: the page
- * @compound: charge the page as compound or small page
- * @from: mem_cgroup which the page is moved from.
- * @to: mem_cgroup which the page is moved to. @from != @to.
+ * mem_cgroup_move_account - move account of the folio
+ * @folio: The folio.
+ * @compound: Charge the folio as large or small.
+ * @from: mem_cgroup which the folio is moved from.
+ * @to: mem_cgroup which the folio is moved to. @from != @to.
*
- * The caller must make sure the page is not on LRU (isolate_page() is useful.)
+ * The caller must make sure the folio is not on LRU (folio_isolate_lru()
+ * is useful.)
*
* This function doesn't do "charge" to new cgroup and doesn't do "uncharge"
* from old cgroup.
*/
-static int mem_cgroup_move_account(struct page *page,
+static int mem_cgroup_move_account(struct folio *folio,
bool compound,
struct mem_cgroup *from,
struct mem_cgroup *to)
{
- struct folio *folio = page_folio(page);
struct lruvec *from_vec, *to_vec;
struct pglist_data *pgdat;
unsigned int nr_pages = compound ? folio_nr_pages(folio) : 1;
@@ -5576,7 +5580,7 @@ static int mem_cgroup_move_account(struct page *page,
/*
* Prevent mem_cgroup_migrate() from looking at
- * page's memory cgroup of its source page while we change it.
+ * folio's memory cgroup of its source folio while we change it.
*/
ret = -EBUSY;
if (!folio_trylock(folio))
@@ -5637,13 +5641,13 @@ static int mem_cgroup_move_account(struct page *page,
/*
* All state has been migrated, let's switch to the new memcg.
*
- * It is safe to change page's memcg here because the page
+ * It is safe to change folio's memcg here because the folio
* is referenced, charged, isolated, and locked: we can't race
* with (un)charging, migration, LRU putback, or anything else
- * that would rely on a stable page's memory cgroup.
+ * that would rely on a stable folio's memory cgroup.
*
- * Note that lock_page_memcg is a memcg lock, not a page lock,
- * to save space. As soon as we switch page's memory cgroup to a
+ * Note that folio_memcg_lock is a memcg lock, not a folio lock,
+ * to save space. As soon as we switch folio's memory cgroup to a
* new memcg that isn't locked, the above state can change
* concurrently again. Make sure we're truly done with it.
*/
@@ -5676,21 +5680,21 @@ static int mem_cgroup_move_account(struct page *page,
* @vma: the vma the pte to be checked belongs
* @addr: the address corresponding to the pte to be checked
* @ptent: the pte to be checked
- * @target: the pointer the target page or swap ent will be stored(can be NULL)
+ * @target: the pointer the target folio or swap ent will be stored(can be NULL)
*
* Returns
* 0(MC_TARGET_NONE): if the pte is not a target for move charge.
- * 1(MC_TARGET_PAGE): if the page corresponding to this pte is a target for
- * move charge. if @target is not NULL, the page is stored in target->page
+ * 1(MC_TARGET_FOLIO): if the folio corresponding to this pte is a target for
+ * move charge. if @target is not NULL, the folio is stored in target->folio
* with extra refcnt got(Callers should handle it).
* 2(MC_TARGET_SWAP): if the swap entry corresponding to this pte is a
* target for charge migration. if @target is not NULL, the entry is stored
* in target->ent.
- * 3(MC_TARGET_DEVICE): like MC_TARGET_PAGE but page is device memory and
+ * 3(MC_TARGET_DEVICE): like MC_TARGET_FOLIO but folio is device memory and
* thus not on the lru.
- * For now we such page is charge like a regular page would be as for all
+ * For now such folio is chargd like a regular folio would be as for all
* intent and purposes it is just special memory taking the place of a
- * regular page.
+ * regular folio.
*
* See Documentations/vm/hmm.txt and include/linux/hmm.h
*
@@ -5700,41 +5704,41 @@ static int mem_cgroup_move_account(struct page *page,
static enum mc_target_type get_mctgt_type(struct vm_area_struct *vma,
unsigned long addr, pte_t ptent, union mc_target *target)
{
- struct page *page = NULL;
+ struct folio *folio = NULL;
enum mc_target_type ret = MC_TARGET_NONE;
swp_entry_t ent = { .val = 0 };
if (pte_present(ptent))
- page = mc_handle_present_pte(vma, addr, ptent);
+ folio = mc_handle_present_pte(vma, addr, ptent);
else if (is_swap_pte(ptent))
- page = mc_handle_swap_pte(vma, ptent, &ent);
+ folio = mc_handle_swap_pte(vma, ptent, &ent);
else if (pte_none(ptent))
- page = mc_handle_file_pte(vma, addr, ptent);
+ folio = mc_handle_file_pte(vma, addr, ptent);
- if (!page && !ent.val)
+ if (!folio && !ent.val)
return ret;
- if (page) {
+ if (folio) {
/*
* Do only loose check w/o serialization.
- * mem_cgroup_move_account() checks the page is valid or
+ * mem_cgroup_move_account() checks the folio is valid or
* not under LRU exclusion.
*/
- if (page_memcg(page) == mc.from) {
- ret = MC_TARGET_PAGE;
- if (is_device_private_page(page) ||
- is_device_coherent_page(page))
+ if (folio_memcg(folio) == mc.from) {
+ ret = MC_TARGET_FOLIO;
+ if (folio_is_device_private(folio) ||
+ folio_is_device_coherent(folio))
ret = MC_TARGET_DEVICE;
if (target)
- target->page = page;
+ target->folio = folio;
}
if (!ret || !target)
- put_page(page);
+ folio_put(folio);
}
/*
- * There is a swap entry and a page doesn't exist or isn't charged.
+ * There is a swap entry and a folio doesn't exist or isn't charged.
* But we cannot move a tail-page in a THP.
*/
- if (ent.val && !ret && (!page || !PageTransCompound(page)) &&
+ if (ent.val && !ret && (!folio || !folio_test_large(folio)) &&
mem_cgroup_id(mc.from) == lookup_swap_cgroup_id(ent)) {
ret = MC_TARGET_SWAP;
if (target)
@@ -5745,14 +5749,14 @@ static enum mc_target_type get_mctgt_type(struct vm_area_struct *vma,
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
/*
- * We don't consider PMD mapped swapping or file mapped pages because THP does
+ * We don't consider PMD mapped swapping or file mapped folios because THP does
* not support them for now.
* Caller should make sure that pmd_trans_huge(pmd) is true.
*/
static enum mc_target_type get_mctgt_type_thp(struct vm_area_struct *vma,
unsigned long addr, pmd_t pmd, union mc_target *target)
{
- struct page *page = NULL;
+ struct folio *folio = NULL;
enum mc_target_type ret = MC_TARGET_NONE;
if (unlikely(is_swap_pmd(pmd))) {
@@ -5760,15 +5764,15 @@ static enum mc_target_type get_mctgt_type_thp(struct vm_area_struct *vma,
!is_pmd_migration_entry(pmd));
return ret;
}
- page = pmd_page(pmd);
- VM_BUG_ON_PAGE(!page || !PageHead(page), page);
+ folio = page_folio(pmd_page(pmd));
+ VM_BUG_ON_FOLIO(!folio || !folio_test_large(folio), folio);
if (!(mc.flags & MOVE_ANON))
return ret;
- if (page_memcg(page) == mc.from) {
- ret = MC_TARGET_PAGE;
+ if (folio_memcg(folio) == mc.from) {
+ ret = MC_TARGET_FOLIO;
if (target) {
- get_page(page);
- target->page = page;
+ folio_get(folio);
+ target->folio = folio;
}
}
return ret;
@@ -5796,7 +5800,8 @@ static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd,
* support transparent huge page with MEMORY_DEVICE_PRIVATE but
* this might change.
*/
- if (get_mctgt_type_thp(vma, addr, *pmd, NULL) == MC_TARGET_PAGE)
+ if (get_mctgt_type_thp(vma, addr, *pmd, NULL) ==
+ MC_TARGET_FOLIO)
mc.precharge += HPAGE_PMD_NR;
spin_unlock(ptl);
return 0;
@@ -5987,7 +5992,7 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd,
spinlock_t *ptl;
enum mc_target_type target_type;
union mc_target target;
- struct page *page;
+ struct folio *folio;
ptl = pmd_trans_huge_lock(pmd, vma);
if (ptl) {
@@ -5996,25 +6001,25 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd,
return 0;
}
target_type = get_mctgt_type_thp(vma, addr, *pmd, &target);
- if (target_type == MC_TARGET_PAGE) {
- page = target.page;
- if (!isolate_lru_page(page)) {
- if (!mem_cgroup_move_account(page, true,
+ if (target_type == MC_TARGET_FOLIO) {
+ folio = target.folio;
+ if (!folio_isolate_lru(folio)) {
+ if (!mem_cgroup_move_account(folio, true,
mc.from, mc.to)) {
mc.precharge -= HPAGE_PMD_NR;
mc.moved_charge += HPAGE_PMD_NR;
}
- putback_lru_page(page);
+ folio_putback_lru(folio);
}
- put_page(page);
+ folio_put(folio);
} else if (target_type == MC_TARGET_DEVICE) {
- page = target.page;
- if (!mem_cgroup_move_account(page, true,
+ folio = target.folio;
+ if (!mem_cgroup_move_account(folio, true,
mc.from, mc.to)) {
mc.precharge -= HPAGE_PMD_NR;
mc.moved_charge += HPAGE_PMD_NR;
}
- put_page(page);
+ folio_put(folio);
}
spin_unlock(ptl);
return 0;
@@ -6036,28 +6041,26 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd,
case MC_TARGET_DEVICE:
device = true;
fallthrough;
- case MC_TARGET_PAGE:
- page = target.page;
+ case MC_TARGET_FOLIO:
+ folio = target.folio;
/*
- * We can have a part of the split pmd here. Moving it
- * can be done but it would be too convoluted so simply
- * ignore such a partial THP and keep it in original
- * memcg. There should be somebody mapping the head.
+ * Is bailing out here with a large folio still the
+ * right thing to do? Unclear.
*/
- if (PageTransCompound(page))
+ if (folio_test_large(folio))
goto put;
- if (!device && isolate_lru_page(page))
+ if (!device && folio_isolate_lru(folio))
goto put;
- if (!mem_cgroup_move_account(page, false,
+ if (!mem_cgroup_move_account(folio, false,
mc.from, mc.to)) {
mc.precharge--;
/* we uncharge from mc.from later. */
mc.moved_charge++;
}
if (!device)
- putback_lru_page(page);
-put: /* get_mctgt_type() gets the page */
- put_page(page);
+ folio_putback_lru(folio);
+put: /* get_mctgt_type() gets the folio */
+ folio_put(folio);
break;
case MC_TARGET_SWAP:
ent = target.ent;