/* * Get an online page for a pfn if it's in the LRU list. Otherwise, returns * NULL. * * The body of this function is stolen from the 'page_idle_get_folio()'. We * steal rather than reuse it because the code is quite simple.
*/ struct folio *damon_get_folio(unsignedlong pfn)
{ struct page *page = pfn_to_online_page(pfn); struct folio *folio;
if (likely(pte_present(pteval)))
pfn = pte_pfn(pteval); else
pfn = swp_offset_pfn(pte_to_swp_entry(pteval));
folio = damon_get_folio(pfn); if (!folio) return;
/* * PFN swap PTEs, such as device-exclusive ones, that actually map pages * are "old" from a CPU perspective. The MMU notifier takes care of any * device aspects.
*/ if (likely(pte_present(pteval)))
young |= ptep_test_and_clear_young(vma, addr, pte);
young |= mmu_notifier_clear_young(vma->vm_mm, addr, addr + PAGE_SIZE); if (young)
folio_set_young(folio);
/* If frequency is 0, higher age means it's colder */ if (freq_subscore == 0)
age_in_log *= -1;
/* * Now age_in_log is in [-DAMON_MAX_AGE_IN_LOG, DAMON_MAX_AGE_IN_LOG]. * Scale it to be in [0, 100] and set it as age subscore.
*/
age_in_log += DAMON_MAX_AGE_IN_LOG;
age_subscore = age_in_log * DAMON_MAX_SUBSCORE /
DAMON_MAX_AGE_IN_LOG / 2;
hotness = (freq_weight * freq_subscore + age_weight * age_subscore); if (freq_weight + age_weight)
hotness /= freq_weight + age_weight; /* * Transform it to fit in [0, DAMOS_MAX_SCORE]
*/
hotness = hotness * DAMOS_MAX_SCORE / DAMON_MAX_SUBSCORE;
return hotness;
}
int damon_cold_score(struct damon_ctx *c, struct damon_region *r, struct damos *s)
{ int hotness = damon_hot_score(c, r, s);
/* Return coldness of the region */ return DAMOS_MAX_SCORE - hotness;
}
/* Relocate its contents to another node. */
list_add(&folio->lru, &migrate_folios);
folio_unlock(folio); continue;
keep:
list_add(&folio->lru, &ret_folios);
} /* 'folio_list' is always empty here */
/* Migrate folios selected for migration */
nr_migrated += __damon_migrate_folio_list(
&migrate_folios, pgdat, target_nid); /* * Folios that could not be migrated are still in @migrate_folios. Add * those back on @folio_list
*/ if (!list_empty(&migrate_folios))
list_splice_init(&migrate_folios, folio_list);
try_to_unmap_flush();
list_splice(&ret_folios, folio_list);
while (!list_empty(folio_list)) {
folio = lru_to_folio(folio_list);
list_del(&folio->lru);
folio_putback_lru(folio);
}
return nr_migrated;
}
unsignedlong damon_migrate_pages(struct list_head *folio_list, int target_nid)
{ int nid; unsignedlong nr_migrated = 0;
LIST_HEAD(node_folio_list); unsignedint noreclaim_flag;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.