mm/gup.c
Source file repositories/reference/linux-study-clean/mm/gup.c
File Facts
- System
- Linux kernel
- Corpus path
mm/gup.c- Extension
.c- Size
- 103284 bytes
- Lines
- 3558
- 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/kernel.hlinux/errno.hlinux/err.hlinux/spinlock.hlinux/mm.hlinux/memfd.hlinux/memremap.hlinux/pagemap.hlinux/rmap.hlinux/swap.hlinux/swapops.hlinux/secretmem.hlinux/sched/signal.hlinux/rwsem.hlinux/hugetlb.hlinux/migrate.hlinux/mm_inline.hlinux/folio_batch.hlinux/sched/mm.hlinux/shmem_fs.hasm/mmu_context.hasm/tlbflush.hinternal.hswap.h
Detected Declarations
struct pages_or_foliosfunction sanity_check_pinned_pagesfunction page_foliofunction gup_put_foliofunction try_grab_foliofunction unpin_user_pagefunction unpin_foliofunction folio_add_pinfunction try_grab_foliofunction unpin_user_pages_dirty_lockfunction clear_page_dirty_for_iofunction unpin_user_page_range_dirty_lockfunction gup_fast_unpin_user_pagesfunction unpin_user_pagesfunction unpin_user_foliofunction unpin_foliosfunction mm_set_has_pinned_flagfunction try_grab_folio_fastfunction can_follow_write_commonfunction get_dump_pagefunction can_follow_write_pudfunction can_follow_write_pmdfunction follow_pfn_ptefunction can_follow_write_ptefunction can_follow_write_ptefunction contentfunction descriptorfunction get_gate_pagefunction faultin_pagefunction unexpectedlyfunction check_vma_flagsfunction __get_user_pagesfunction try_grab_foliofunction vma_permits_faultfunction fixup_user_faultfunction gup_signal_pendingfunction setfunction populate_vma_page_rangefunction faultin_page_rangefunction mlockfunction __get_user_pages_lockedfunction infunction copy_to_userfunction fault_in_writeablefunction infunction mmap_lockfunction pofs_clear_entryfunction pofs_unpin
Annotated Snippet
* page tables. Return error instead of NULL to skip handle_mm_fault,
* then get_dump_page() will return NULL to leave a hole in the dump.
* But we can only make this optimization where a hole would surely
* be zero-filled if handle_mm_fault() actually did handle it.
*/
if (is_vm_hugetlb_page(vma)) {
struct hstate *h = hstate_vma(vma);
if (!hugetlbfs_pagecache_present(h, vma, address))
return ERR_PTR(-EFAULT);
} else if ((vma_is_anonymous(vma) || !vma->vm_ops->fault)) {
return ERR_PTR(-EFAULT);
}
return NULL;
}
#ifdef CONFIG_PGTABLE_HAS_HUGE_LEAVES
/* FOLL_FORCE can write to even unwritable PUDs in COW mappings. */
static inline bool can_follow_write_pud(pud_t pud, struct page *page,
struct vm_area_struct *vma,
unsigned int flags)
{
/* If the pud is writable, we can write to the page. */
if (pud_write(pud))
return true;
return can_follow_write_common(page, vma, flags);
}
static struct page *follow_huge_pud(struct vm_area_struct *vma,
unsigned long addr, pud_t *pudp,
int flags, unsigned long *page_mask)
{
struct mm_struct *mm = vma->vm_mm;
struct page *page;
pud_t pud = *pudp;
unsigned long pfn = pud_pfn(pud);
int ret;
assert_spin_locked(pud_lockptr(mm, pudp));
if (!pud_present(pud))
return NULL;
if ((flags & FOLL_WRITE) &&
!can_follow_write_pud(pud, pfn_to_page(pfn), vma, flags))
return NULL;
pfn += (addr & ~PUD_MASK) >> PAGE_SHIFT;
page = pfn_to_page(pfn);
if (!pud_write(pud) && gup_must_unshare(vma, flags, page))
return ERR_PTR(-EMLINK);
ret = try_grab_folio(page_folio(page), 1, flags);
if (ret)
page = ERR_PTR(ret);
else
*page_mask = HPAGE_PUD_NR - 1;
return page;
}
/* FOLL_FORCE can write to even unwritable PMDs in COW mappings. */
static inline bool can_follow_write_pmd(pmd_t pmd, struct page *page,
struct vm_area_struct *vma,
unsigned int flags)
{
/* If the pmd is writable, we can write to the page. */
if (pmd_write(pmd))
return true;
if (!can_follow_write_common(page, vma, flags))
return false;
/* ... and a write-fault isn't required for other reasons. */
if (pmd_needs_soft_dirty_wp(vma, pmd))
return false;
return !userfaultfd_huge_pmd_wp(vma, pmd);
}
static struct page *follow_huge_pmd(struct vm_area_struct *vma,
unsigned long addr, pmd_t *pmd,
unsigned int flags,
unsigned long *page_mask)
{
struct mm_struct *mm = vma->vm_mm;
pmd_t pmdval = *pmd;
struct page *page;
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/errno.h`, `linux/err.h`, `linux/spinlock.h`, `linux/mm.h`, `linux/memfd.h`, `linux/memremap.h`, `linux/pagemap.h`.
- Detected declarations: `struct pages_or_folios`, `function sanity_check_pinned_pages`, `function page_folio`, `function gup_put_folio`, `function try_grab_folio`, `function unpin_user_page`, `function unpin_folio`, `function folio_add_pin`, `function try_grab_folio`, `function unpin_user_pages_dirty_lock`.
- 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.