tools/testing/selftests/mm/uffd-common.c
Source file repositories/reference/linux-study-clean/tools/testing/selftests/mm/uffd-common.c
File Facts
- System
- Linux kernel
- Corpus path
tools/testing/selftests/mm/uffd-common.c- Extension
.c- Size
- 20509 bytes
- Lines
- 746
- Domain
- Support Tooling And Documentation
- Bucket
- tools
- Inferred role
- Support Tooling And Documentation: implementation source
- Status
- source implementation candidate
Why This File Exists
Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
uffd-common.h
Detected Declarations
function uffd_mem_fd_createfunction anon_release_pagesfunction anon_allocate_areafunction noop_alias_mappingfunction hugetlb_allocate_areafunction hugetlb_alias_mappingfunction shmem_release_pagesfunction shmem_allocate_areafunction shmem_alias_mappingfunction shmem_check_pmd_mappingfunction uffd_stats_reportfunction userfaultfd_openfunction munmap_areafunction uffd_test_ctx_clearfunction uffd_test_ctx_initfunction wp_rangefunction continue_rangefunction uffd_read_msgfunction uffd_handle_page_faultfunction retry_copy_pagefunction wake_rangefunction __copy_pagefunction copy_pagefunction move_pagefunction uffd_open_devfunction uffd_open_sysfunction uffd_openfunction uffd_get_features
Annotated Snippet
if (ret < 0) {
if (errno == EAGAIN || errno == EINTR)
return 1;
err("blocking read error");
} else {
err("short read");
}
}
return 0;
}
void uffd_handle_page_fault(uffd_global_test_opts_t *gopts, struct uffd_msg *msg,
struct uffd_args *args)
{
unsigned long offset;
if (msg->event != UFFD_EVENT_PAGEFAULT)
err("unexpected msg event %u", msg->event);
if (msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WP) {
/* Write protect page faults */
wp_range(gopts->uffd, msg->arg.pagefault.address, gopts->page_size, false);
args->wp_faults++;
} else if (msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_MINOR) {
uint8_t *area;
int b;
/*
* Minor page faults
*
* To prove we can modify the original range for testing
* purposes, we're going to bit flip this range before
* continuing.
*
* Note that this requires all minor page fault tests operate on
* area_dst (non-UFFD-registered) and area_dst_alias
* (UFFD-registered).
*/
area = (uint8_t *)(gopts->area_dst +
((char *)msg->arg.pagefault.address -
gopts->area_dst_alias));
for (b = 0; b < gopts->page_size; ++b)
area[b] = ~area[b];
continue_range(gopts->uffd, msg->arg.pagefault.address, gopts->page_size,
args->apply_wp);
args->minor_faults++;
} else {
/*
* Missing page faults.
*
* Here we force a write check for each of the missing mode
* faults. It's guaranteed because the only threads that
* will trigger uffd faults are the locking threads, and
* their first instruction to touch the missing page will
* always be pthread_mutex_lock().
*
* Note that here we relied on an NPTL glibc impl detail to
* always read the lock type at the entry of the lock op
* (pthread_mutex_t.__data.__type, offset 0x10) before
* doing any locking operations to guarantee that. It's
* actually not good to rely on this impl detail because
* logically a pthread-compatible lib can implement the
* locks without types and we can fail when linking with
* them. However since we used to find bugs with this
* strict check we still keep it around. Hopefully this
* could be a good hint when it fails again. If one day
* it'll break on some other impl of glibc we'll revisit.
*/
if (msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)
err("unexpected write fault");
offset = (char *)(unsigned long)msg->arg.pagefault.address - gopts->area_dst;
offset &= ~(gopts->page_size-1);
if (copy_page(gopts, offset, args->apply_wp))
args->missing_faults++;
}
}
void *uffd_poll_thread(void *arg)
{
struct uffd_args *args = (struct uffd_args *)arg;
uffd_global_test_opts_t *gopts = args->gopts;
unsigned long cpu = args->cpu;
struct pollfd pollfd[2];
struct uffd_msg msg;
struct uffdio_register uffd_reg;
int ret;
Annotation
- Immediate include surface: `uffd-common.h`.
- Detected declarations: `function uffd_mem_fd_create`, `function anon_release_pages`, `function anon_allocate_area`, `function noop_alias_mapping`, `function hugetlb_allocate_area`, `function hugetlb_alias_mapping`, `function shmem_release_pages`, `function shmem_allocate_area`, `function shmem_alias_mapping`, `function shmem_check_pmd_mapping`.
- Atlas domain: Support Tooling And Documentation / tools.
- Implementation status: source implementation candidate.
- 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.