mm/ksm.c
Source file repositories/reference/linux-study-clean/mm/ksm.c
File Facts
- System
- Linux kernel
- Corpus path
mm/ksm.c- Extension
.c- Size
- 112035 bytes
- Lines
- 4022
- 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.
- Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/errno.hlinux/mm.hlinux/mm_inline.hlinux/fs.hlinux/mman.hlinux/sched.hlinux/sched/mm.hlinux/sched/cputime.hlinux/rwsem.hlinux/pagemap.hlinux/rmap.hlinux/spinlock.hlinux/xxhash.hlinux/delay.hlinux/kthread.hlinux/wait.hlinux/slab.hlinux/rbtree.hlinux/memory.hlinux/mmu_notifier.hlinux/swap.hlinux/ksm.hlinux/hashtable.hlinux/freezer.hlinux/oom.hlinux/numa.hlinux/pagewalk.hasm/tlbflush.hinternal.hmm_slot.htrace/events/ksm.h
Detected Declarations
struct ksm_mm_slotstruct ksm_scanstruct ksm_stable_nodestruct ksm_rmap_itemstruct advisor_ctxstruct ksm_next_page_argenum ksm_advisor_typeenum ksm_get_folio_flagsfunction set_advisor_defaultsfunction advisor_start_scanfunction prev_scan_timefunction ewmafunction scan_time_advisorfunction advisor_stop_scanfunction ksm_slab_initfunction ksm_slab_freefunction is_stable_node_chainfunction is_stable_node_dupfunction stable_node_chain_add_dupfunction __stable_node_dup_delfunction stable_node_dup_delfunction free_rmap_itemfunction free_stable_nodefunction ksm_exitfunction break_ksm_pmd_entryfunction timefunction ksm_compatiblefunction vma_ksm_compatiblefunction break_cowfunction get_kpfn_nidfunction free_stable_node_chainfunction remove_node_from_stable_treefunction hlist_for_each_entryfunction folio_migrate_mappingfunction remove_rmap_item_from_treefunction remove_trailing_rmap_itemsfunction folio_set_stable_nodefunction remove_stable_nodefunction remove_stable_node_chainfunction hlist_for_each_entry_safefunction remove_all_stable_nodesfunction unmerge_and_remove_all_rmap_itemsfunction for_each_vmafunction calc_checksumfunction write_protect_pagefunction replace_pagefunction try_to_merge_one_pagefunction candidates
Annotated Snippet
ret = handle_mm_fault(vma, addr,
FAULT_FLAG_UNSHARE | FAULT_FLAG_REMOTE,
NULL);
} while (!(ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | VM_FAULT_OOM)));
/*
* We must loop until we no longer find a KSM page because
* handle_mm_fault() may back out if there's any difficulty e.g. if
* pte accessed bit gets updated concurrently.
*
* VM_FAULT_SIGBUS could occur if we race with truncation of the
* backing file, which also invalidates anonymous pages: that's
* okay, that truncation will have unmapped the KSM page for us.
*
* VM_FAULT_OOM: at the time of writing (late July 2009), setting
* aside mem_cgroup limits, VM_FAULT_OOM would only be set if the
* current task has TIF_MEMDIE set, and will be OOM killed on return
* to user; and ksmd, having no mm, would never be chosen for that.
*
* But if the mm is in a limited mem_cgroup, then the fault may fail
* with VM_FAULT_OOM even if the current task is not TIF_MEMDIE; and
* even ksmd can fail in this way - though it's usually breaking ksm
* just to undo a merge it made a moment before, so unlikely to oom.
*
* That's a pity: we might therefore have more kernel pages allocated
* than we're counting as nodes in the stable tree; but ksm_do_scan
* will retry to break_cow on each pass, so should recover the page
* in due course. The important thing is to not let VM_MERGEABLE
* be cleared while any such pages might remain in the area.
*/
return (ret & VM_FAULT_OOM) ? -ENOMEM : 0;
}
static bool ksm_compatible(const struct file *file, vma_flags_t vma_flags)
{
/* Just ignore the advice. */
if (vma_flags_test_any(&vma_flags, VMA_SHARED_BIT, VMA_MAYSHARE_BIT,
VMA_HUGETLB_BIT))
return false;
if (vma_flags_test_single_mask(&vma_flags, VMA_DROPPABLE))
return false;
if (vma_flags_test_any_mask(&vma_flags, VMA_SPECIAL_FLAGS))
return false;
if (file_is_dax(file))
return false;
#ifdef VM_SAO
if (vma_flags_test(&vma_flags, VMA_SAO_BIT))
return false;
#endif
#ifdef VM_SPARC_ADI
if (vma_flags_test(&vma_flags, VMA_SPARC_ADI_BIT))
return false;
#endif
return true;
}
static bool vma_ksm_compatible(struct vm_area_struct *vma)
{
return ksm_compatible(vma->vm_file, vma->flags);
}
static struct vm_area_struct *find_mergeable_vma(struct mm_struct *mm,
unsigned long addr)
{
struct vm_area_struct *vma;
if (ksm_test_exit(mm))
return NULL;
vma = vma_lookup(mm, addr);
if (!vma || !(vma->vm_flags & VM_MERGEABLE) || !vma->anon_vma)
return NULL;
return vma;
}
static void break_cow(struct ksm_rmap_item *rmap_item)
{
struct mm_struct *mm = rmap_item->mm;
unsigned long addr = rmap_item->address;
struct vm_area_struct *vma;
/*
* It is not an accident that whenever we want to break COW
* to undo, we also need to drop a reference to the anon_vma.
*/
put_anon_vma(rmap_item->anon_vma);
mmap_read_lock(mm);
vma = find_mergeable_vma(mm, addr);
if (vma)
break_ksm(vma, addr, addr + PAGE_SIZE, false);
mmap_read_unlock(mm);
Annotation
- Immediate include surface: `linux/errno.h`, `linux/mm.h`, `linux/mm_inline.h`, `linux/fs.h`, `linux/mman.h`, `linux/sched.h`, `linux/sched/mm.h`, `linux/sched/cputime.h`.
- Detected declarations: `struct ksm_mm_slot`, `struct ksm_scan`, `struct ksm_stable_node`, `struct ksm_rmap_item`, `struct advisor_ctx`, `struct ksm_next_page_arg`, `enum ksm_advisor_type`, `enum ksm_get_folio_flags`, `function set_advisor_defaults`, `function advisor_start_scan`.
- Atlas domain: Core OS / Memory Management.
- Implementation status: integration implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.