mm/page_isolation.c

Source file repositories/reference/linux-study-clean/mm/page_isolation.c

File Facts

System
Linux kernel
Corpus path
mm/page_isolation.c
Extension
.c
Size
19951 bytes
Lines
644
Domain
Core OS
Bucket
Memory Management
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (folio_test_hugetlb(folio)) {
			struct hstate *h;

			if (!IS_ENABLED(CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION))
				return true;

			/*
			 * The huge page may be freed so can not
			 * use folio_hstate() directly.
			 */
			h = size_to_hstate(folio_size(folio));
			if (h && !hugepage_migration_supported(h))
				return true;

		} else if (!folio_test_lru(folio)) {
			return true;
		}

		*step = folio_nr_pages(folio) - folio_page_idx(folio, page);
		return false;
	}

	/*
	 * We can't use page_count without pin a page
	 * because another CPU can free compound page.
	 * This check already skips compound tails of THP
	 * because their page->_refcount is zero at all time.
	 */
	if (!page_ref_count(page)) {
		if (PageBuddy(page))
			*step = (1 << buddy_order(page));
		return false;
	}

	/*
	 * The HWPoisoned page may be not in buddy system, and
	 * page_count() is not 0.
	 */
	if ((mode == PB_ISOLATE_MODE_MEM_OFFLINE) && PageHWPoison(page))
		return false;

	/*
	 * We treat all PageOffline() pages as movable when offlining
	 * to give drivers a chance to decrement their reference count
	 * in MEM_GOING_OFFLINE in order to indicate that these pages
	 * can be offlined as there are no direct references anymore.
	 * For actually unmovable PageOffline() where the driver does
	 * not support this, we will fail later when trying to actually
	 * move these pages that still have a reference count > 0.
	 * (false negatives in this function only)
	 */
	if ((mode == PB_ISOLATE_MODE_MEM_OFFLINE) && PageOffline(page))
		return false;

	if (PageLRU(page) || page_has_movable_ops(page))
		return false;

	/*
	 * If there are RECLAIMABLE pages, we need to check
	 * it.  But now, memory offline itself doesn't call
	 * shrink_node_slabs() and it still to be fixed.
	 */
	return true;
}

/*
 * This function checks whether the range [start_pfn, end_pfn) includes
 * unmovable pages or not. The range must fall into a single pageblock and
 * consequently belong to a single zone.
 *
 * PageLRU check without isolation or lru_lock could race so that
 * MIGRATE_MOVABLE block might include unmovable pages. Similarly, pages
 * with movable_ops can only be identified some time after they were
 * allocated. So you can't expect this function should be exact.
 *
 * Returns a page without holding a reference. If the caller wants to
 * dereference that page (e.g., dumping), it has to make sure that it
 * cannot get removed (e.g., via memory unplug) concurrently.
 *
 */
static struct page *has_unmovable_pages(unsigned long start_pfn, unsigned long end_pfn,
				enum pb_isolate_mode mode)
{
	struct page *page = pfn_to_page(start_pfn);
	struct zone *zone = page_zone(page);

	VM_BUG_ON(pageblock_start_pfn(start_pfn) !=
		  pageblock_start_pfn(end_pfn - 1));

	if (is_migrate_cma_page(page)) {

Annotation

Implementation Notes