diff --git a/Documentation/under-the-hood/userfaultfd.md b/Documentation/under-the-hood/userfaultfd.md index e6daa28a7..9a5060454 100644 --- a/Documentation/under-the-hood/userfaultfd.md +++ b/Documentation/under-the-hood/userfaultfd.md @@ -1,33 +1,48 @@ -# Userfaultfd +# Userfaultfd and Lazy Migration -This article describes the use of `userfaultfd` for lazy restoration and lazy migration in CRIU. +**Userfaultfd** is a powerful Linux kernel feature that allows a userspace process (a "monitor") to handle page faults for other processes. CRIU leverages this feature to implement **Lazy Migration**, which significantly reduces the initial downtime when migrating memory-intensive applications. -## Background -The [`userfaultfd`](http://man7.org/linux/man-pages/man2/userfaultfd.2.html) mechanism allows for userspace-driven paging. While its initial implementation in Linux 4.3 was tailored for KVM/QEMU, Linux 4.11 introduced a "non-cooperative" mode that enables lazy (or post-copy) restoration in CRIU. +## Lazy Migration Overview -## Concepts +In a traditional migration, the destination host must receive the entire memory dump (potentially many gigabytes) before the application can resume. This "freeze time" can be several seconds or even minutes for large applications. -- **Lazy Restoration**: The `restore` command includes a `--lazy-pages` option. In this mode, CRIU skips injecting memory pages into the process's address space and instead registers those areas with `userfaultfd`. -- **Lazy-Pages Daemon**: A dedicated daemon manages these lazy memory areas. It receives `userfault` file descriptors from CRIU via a UNIX socket, allowing it to intercept and resolve page faults and other memory events. -- **Lazy Migration**: The `dump` command also supports the `--lazy-pages` option. When enabled, the dumper retains the memory pages and allows the `lazy-pages` daemon to request them via a TCP connection as needed. +With **Lazy Migration**: +1. CRIU captures only the minimal process state (registers, file descriptors, etc.) and essential memory pages. +2. The process tree is resumed immediately on the destination host with most of its memory regions mapped but empty. +3. Memory pages are transferred from the source host only when the application actually tries to access them ("on-demand"). -![File:Criu-memory-wflow.png](File:Criu-memory-wflow.png) +## How it Works: The Lazy Pages Daemon -### The Daemon -After restoration, processes have lazy VMAs registered with `userfaultfd`. The `userfaultfd` descriptor is sent to the `lazy-pages` daemon before the processes resume. The daemon then monitors for UFFD events and populates the address spaces. It can retrieve pages from local images, remote images, or directly from a remote dumper. +CRIU implements lazy migration through a dedicated background process called the **Lazy Pages Daemon**. -When a restored task accesses a missing page, a page fault occurs. The `lazy-pages` daemon receives this notification and populates the required memory. To optimize the process, the daemon also proactively copies remaining memory pages in the background when no faults are pending. +### 1. The Handover +During the restoration process, each process in the tree: +* Opens a `userfaultfd` file descriptor. +* Registers its memory regions with the kernel for tracking. +* Sends the descriptor to the Lazy Pages Daemon via a Unix domain socket using the `SCM_RIGHTS` mechanism. +* Resumes execution of the application code via `sigreturn`. -#### Local and Remote Sources -- **Local Images**: The daemon uses a local engine to read pages from image files. -- **Remote Images**: The [page server](page-server.md) is run on the remote host with the `--lazy-pages` option. The daemon connects to it using the `--page-server`, `--address`, and `--port` options. -- **Migration**: During migration, the `dump` process collects pages into pipes and starts a page server. The daemon requests missing pages from this server and injects them into the task's address space using `userfaultfd`. +### 2. Handling Page Faults +When the application accesses a page that hasn't been loaded yet, the kernel pauses the faulting thread and sends a message to the Lazy Pages Daemon. +1. **Notification**: The daemon receives a `UFFD_EVENT_PAGEFAULT` message containing the faulting address. +2. **Retrieval**: The daemon fetches the required page contents, either from the local `pages.img` images or from a remote **Page Server** on the source host. +3. **Injection**: The daemon uses the `UFFDIO_COPY` (to fill data) or `UFFDIO_ZEROPAGE` (to fill zeros) ioctl to inject the page into the application's address space. +4. **Resumption**: Once the kernel confirms the page is filled, it automatically resumes the paused thread. -## Limitations +## Advanced Features: Non-Cooperative UFFD -- Currently, only `MAP_PRIVATE | MAP_ANONYMOUS` mappings are supported. While newer kernels (4.11+) support `userfaultfd` for `hugetlbfs` and shared memory, these features are not yet implemented in CRIU. -- `userfaultfd` does not support mapping a single page into multiple locations simultaneously. Consequently, COW-ed pages remain COW-ed. +CRIU utilizes "non-cooperative" kernel features to maintain consistency if the application modifies its memory layout while being lazily restored: +* **UFFD_FEATURE_EVENT_FORK**: If the process calls `fork()`, the kernel notifies the daemon, which then begins monitoring the new child process. +* **UFFD_FEATURE_EVENT_REMAP**: If the process moves memory using `mremap()`, the daemon updates its internal mapping table to ensure it continues to fetch the correct data for the new addresses. +* **UFFD_FEATURE_EVENT_UNMAP / REMOVE**: Handles scenarios where the application releases memory. + +## Benefits and Trade-offs + +* **Reduced Downtime**: Applications resume in milliseconds, regardless of their total memory size. +* **Network Jitter**: The application may experience minor stalls (latency spikes) during the initial phase as pages are fetched over the network. +* **Source Dependency**: The source host and the Page Server must remain alive and connected until the entire memory state has been successfully transferred to the destination. ## See also -- [Disk-less migration](disk-less-migration.md) -- [Lazy migration](lazy-migration.md) +* [Memory Dumping and Restoring](memory-dumping-and-restoring.md) +* [Page Server](page-server.md) +* [Kerndat Feature Detection](kerndat.md)