History

userfaultfd: add UFFDIO_CONTINUE ioctl

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.)

Axel Rasmussen committed 5 years ago

Commit f6191471 parent 714c1896 files · +156 −30Browse files

Showing the changes to include/uapi/linux (1 of 6 files). Show all

Unified · Split

include/uapi/linux/userfaultfd.h+19−2
@@ -40,10 +40,12 @@ · 39 unmodified lines
40 ((__u64)1 << _UFFDIO_WAKE | \40 ((__u64)1 << _UFFDIO_WAKE | \
41 (__u64)1 << _UFFDIO_COPY | \41 (__u64)1 << _UFFDIO_COPY | \
42 (__u64)1 << _UFFDIO_ZEROPAGE | \42 (__u64)1 << _UFFDIO_ZEROPAGE | \
43 (__u64)1 << _UFFDIO_WRITEPROTECT)43 (__u64)1 << _UFFDIO_WRITEPROTECT | \
44 (__u64)1 << _UFFDIO_CONTINUE)
44#define UFFD_API_RANGE_IOCTLS_BASIC \45#define UFFD_API_RANGE_IOCTLS_BASIC \
45 ((__u64)1 << _UFFDIO_WAKE | \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 * Valid ioctl command number range with this API is from 0x00 to51 * Valid ioctl command number range with this API is from 0x00 to
@@ -59,6 +61,7 @@ · 9 unmodified lines
59#define _UFFDIO_COPY (0x03)61#define _UFFDIO_COPY (0x03)
60#define _UFFDIO_ZEROPAGE (0x04)62#define _UFFDIO_ZEROPAGE (0x04)
61#define _UFFDIO_WRITEPROTECT (0x06)63#define _UFFDIO_WRITEPROTECT (0x06)
64#define _UFFDIO_CONTINUE (0x07)
62#define _UFFDIO_API (0x3F)65#define _UFFDIO_API (0x3F)
63 66
64/* userfaultfd ioctl ids */67/* userfaultfd ioctl ids */
@@ -77,6 +80,8 @@ · 12 unmodified lines
77 struct uffdio_zeropage)80 struct uffdio_zeropage)
78#define UFFDIO_WRITEPROTECT _IOWR(UFFDIO, _UFFDIO_WRITEPROTECT, \81#define UFFDIO_WRITEPROTECT _IOWR(UFFDIO, _UFFDIO_WRITEPROTECT, \
79 struct uffdio_writeprotect)82 struct uffdio_writeprotect)
83#define UFFDIO_CONTINUE _IOR(UFFDIO, _UFFDIO_CONTINUE, \
84 struct uffdio_continue)
80 85
81/* read() structure */86/* read() structure */
82struct uffd_msg {87struct uffd_msg {
@@ -268,6 +273,18 @@ struct uffdio_writeprotect { · 185 unmodified lines
268 __u64 mode;273 __u64 mode;
269};274};
270 275
276struct 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 * Flags for the userfaultfd(2) system call itself.289 * Flags for the userfaultfd(2) system call itself.
273 */290 */