mm/rmap.c

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

File Facts

System
Linux kernel
Corpus path
mm/rmap.c
Extension
.c
Size
94438 bytes
Lines
3156
Domain
Core OS
Bucket
Memory Management
Inferred role
Core OS: exported/initcall integration point
Status
integration 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

struct folio_referenced_arg {
	int mapcount;
	int referenced;
	vm_flags_t vm_flags;
	struct mem_cgroup *memcg;
};

/*
 * arg: folio_referenced_arg will be passed
 */
static bool folio_referenced_one(struct folio *folio,
		struct vm_area_struct *vma, unsigned long address, void *arg)
{
	struct folio_referenced_arg *pra = arg;
	DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, address, 0);
	int ptes = 0, referenced = 0;
	unsigned int nr;

	while (page_vma_mapped_walk(&pvmw)) {
		address = pvmw.address;
		nr = 1;

		if (vma->vm_flags & VM_LOCKED) {
			ptes++;
			pra->mapcount--;

			/* Only mlock fully mapped pages */
			if (pvmw.pte && ptes != pvmw.nr_pages)
				continue;

			/*
			 * All PTEs must be protected by page table lock in
			 * order to mlock the page.
			 *
			 * If page table boundary has been cross, current ptl
			 * only protect part of ptes.
			 */
			if (pvmw.flags & PVMW_PGTABLE_CROSSED)
				continue;

			/* Restore the mlock which got missed */
			mlock_vma_folio(folio, vma);
			page_vma_mapped_walk_done(&pvmw);
			pra->vm_flags |= VM_LOCKED;
			return false; /* To break the loop */
		}

		/*
		 * Skip the non-shared swapbacked folio mapped solely by
		 * the exiting or OOM-reaped process. This avoids redundant
		 * swap-out followed by an immediate unmap.
		 */
		if ((!atomic_read(&vma->vm_mm->mm_users) ||
		    check_stable_address_space(vma->vm_mm)) &&
		    folio_test_anon(folio) && folio_test_swapbacked(folio) &&
		    !folio_maybe_mapped_shared(folio)) {
			pra->referenced = -1;
			page_vma_mapped_walk_done(&pvmw);
			return false;
		}

		if (pvmw.pte && folio_test_large(folio)) {
			const unsigned long end_addr = pmd_addr_end(address, vma->vm_end);
			const unsigned int max_nr = (end_addr - address) >> PAGE_SHIFT;
			pte_t pteval = ptep_get(pvmw.pte);

			nr = folio_pte_batch(folio, pvmw.pte, pteval, max_nr);
		}

		/*
		 * When LRU is switching, we don’t know where the surrounding folios
		 * are. —they could be on active/inactive lists or on MGLRU. So the
		 * simplest approach is to disable this look-around optimization.
		 */
		if (lru_gen_enabled() && !lru_gen_switching() && pvmw.pte) {
			if (lru_gen_look_around(&pvmw, nr))
				referenced++;
		} else if (pvmw.pte) {
			if (clear_flush_young_ptes_notify(vma, address, pvmw.pte, nr))
				referenced++;
		} else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
			if (pmdp_clear_flush_young_notify(vma, address,
						pvmw.pmd))
				referenced++;
		} else {
			/* unexpected pmd-mapped folio? */
			WARN_ON_ONCE(1);
		}

		ptes += nr;

Annotation

Implementation Notes