This ioctl is how userspace ought to resolve "minor" userfaults. The idea is, userspace is notified that a minor fault has occurred. It might change the contents of the page using its second non-UFFD mapping, or not. Then, it calls UFFDIO_CONTINUE to tell the kernel "I have ensured the page contents are correct, carry on setting up the mapping". Note that it doesn't make much sense to use UFFDIO_{COPY,ZEROPAGE} for MINOR registered VMAs. ZEROPAGE maps the VMA to the zero page; but in the minor fault case, we already have some pre-existing underlying page. Likewise, UFFDIO_COPY isn't useful if we have a second non-UFFD mapping. We'd just use memcpy() or similar instead. It turns out hugetlb_mcopy_atomic_pte() already does very close to what we want, if an existing page is provided via `struct page **pagep`. We already special-case the behavior a bit for the UFFDIO_ZEROPAGE case, so just extend that design: add an enum for the three modes of operation, and make the small adjustments needed for the MCOPY_ATOMIC_CONTINUE case. (Basically, look up the existing page, and avoid adding the existing page to the page cache or calling set_page_huge_active() on it.)
Showing the changes to include/uapi/linux (1 of 6 files). Show all
Unified · Split
| @@ -40,10 +40,12 @@ · 39 unmodified lines | ||
| 40 | 40 | ((__u64)1 << _UFFDIO_WAKE | \ |
| 41 | 41 | (__u64)1 << _UFFDIO_COPY | \ |
| 42 | 42 | (__u64)1 << _UFFDIO_ZEROPAGE | \ |
| 43 | − (__u64)1 << _UFFDIO_WRITEPROTECT) | |
| 43 | + (__u64)1 << _UFFDIO_WRITEPROTECT | \ | |
| 44 | + (__u64)1 << _UFFDIO_CONTINUE) | |
| 44 | 45 | #define UFFD_API_RANGE_IOCTLS_BASIC \ |
| 45 | 46 | ((__u64)1 << _UFFDIO_WAKE | \ |
| 46 | − (__u64)1 << _UFFDIO_COPY) | |
| 47 | + (__u64)1 << _UFFDIO_COPY | \ | |
| 48 | + (__u64)1 << _UFFDIO_CONTINUE) | |
| 47 | 49 | |
| 48 | 50 | /* |
| 49 | 51 | * Valid ioctl command number range with this API is from 0x00 to |
| @@ -59,6 +61,7 @@ · 9 unmodified lines | ||
| 59 | 61 | #define _UFFDIO_COPY (0x03) |
| 60 | 62 | #define _UFFDIO_ZEROPAGE (0x04) |
| 61 | 63 | #define _UFFDIO_WRITEPROTECT (0x06) |
| 64 | +#define _UFFDIO_CONTINUE (0x07) | |
| 62 | 65 | #define _UFFDIO_API (0x3F) |
| 63 | 66 | |
| 64 | 67 | /* userfaultfd ioctl ids */ |
| @@ -77,6 +80,8 @@ · 12 unmodified lines | ||
| 77 | 80 | struct uffdio_zeropage) |
| 78 | 81 | #define UFFDIO_WRITEPROTECT _IOWR(UFFDIO, _UFFDIO_WRITEPROTECT, \ |
| 79 | 82 | struct uffdio_writeprotect) |
| 83 | +#define UFFDIO_CONTINUE _IOR(UFFDIO, _UFFDIO_CONTINUE, \ | |
| 84 | + struct uffdio_continue) | |
| 80 | 85 | |
| 81 | 86 | /* read() structure */ |
| 82 | 87 | struct uffd_msg { |
| @@ -268,6 +273,18 @@ struct uffdio_writeprotect { · 185 unmodified lines | ||
| 268 | 273 | __u64 mode; |
| 269 | 274 | }; |
| 270 | 275 | |
| 276 | +struct uffdio_continue { | |
| 277 | + struct uffdio_range range; | |
| 278 | +#define UFFDIO_CONTINUE_MODE_DONTWAKE ((__u64)1<<0) | |
| 279 | + __u64 mode; | |
| 280 | + | |
| 281 | + /* | |
| 282 | + * Fields below here are written by the ioctl and must be at the end: | |
| 283 | + * the copy_from_user will not read past here. | |
| 284 | + */ | |
| 285 | + __s64 mapped; | |
| 286 | +}; | |
| 287 | + | |
| 271 | 288 | /* |
| 272 | 289 | * Flags for the userfaultfd(2) system call itself. |
| 273 | 290 | */ |