Skip to content

Commit

Permalink
userfaultfd: non-cooperative: add madvise() event for MADV_DONTNEED r…
Browse files Browse the repository at this point in the history
…equest

If the page is punched out of the address space the uffd reader should
know this and zeromap the respective area in case of the #PF event.

Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Pavel Emelyanov <[email protected]>
Signed-off-by: Mike Rapoport <[email protected]>
Signed-off-by: Andrea Arcangeli <[email protected]>
Cc: "Dr. David Alan Gilbert" <[email protected]>
Cc: Hillf Danton <[email protected]>
Cc: Michael Rapoport <[email protected]>
Cc: Mike Kravetz <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
xemul authored and torvalds committed Feb 23, 2017
1 parent 90794bf commit 05ce772
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 1 deletion.
28 changes: 28 additions & 0 deletions fs/userfaultfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,34 @@ void mremap_userfaultfd_complete(struct vm_userfaultfd_ctx *vm_ctx,
userfaultfd_event_wait_completion(ctx, &ewq);
}

void madvise_userfault_dontneed(struct vm_area_struct *vma,
struct vm_area_struct **prev,
unsigned long start, unsigned long end)
{
struct mm_struct *mm = vma->vm_mm;
struct userfaultfd_ctx *ctx;
struct userfaultfd_wait_queue ewq;

ctx = vma->vm_userfaultfd_ctx.ctx;
if (!ctx || !(ctx->features & UFFD_FEATURE_EVENT_MADVDONTNEED))
return;

userfaultfd_ctx_get(ctx);
up_read(&mm->mmap_sem);

*prev = NULL; /* We wait for ACK w/o the mmap semaphore */

msg_init(&ewq.msg);

ewq.msg.event = UFFD_EVENT_MADVDONTNEED;
ewq.msg.arg.madv_dn.start = start;
ewq.msg.arg.madv_dn.end = end;

userfaultfd_event_wait_completion(ctx, &ewq);

down_read(&mm->mmap_sem);
}

static int userfaultfd_release(struct inode *inode, struct file *file)
{
struct userfaultfd_ctx *ctx = file->private_data;
Expand Down
12 changes: 12 additions & 0 deletions include/linux/userfaultfd_k.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ extern void mremap_userfaultfd_complete(struct vm_userfaultfd_ctx *,
unsigned long from, unsigned long to,
unsigned long len);

extern void madvise_userfault_dontneed(struct vm_area_struct *vma,
struct vm_area_struct **prev,
unsigned long start,
unsigned long end);

#else /* CONFIG_USERFAULTFD */

/* mm helpers */
Expand Down Expand Up @@ -106,6 +111,13 @@ static inline void mremap_userfaultfd_complete(struct vm_userfaultfd_ctx *ctx,
unsigned long len)
{
}

static inline void madvise_userfault_dontneed(struct vm_area_struct *vma,
struct vm_area_struct **prev,
unsigned long start,
unsigned long end)
{
}
#endif /* CONFIG_USERFAULTFD */

#endif /* _LINUX_USERFAULTFD_K_H */
10 changes: 9 additions & 1 deletion include/uapi/linux/userfaultfd.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
*/
#define UFFD_API ((__u64)0xAA)
#define UFFD_API_FEATURES (UFFD_FEATURE_EVENT_FORK | \
UFFD_FEATURE_EVENT_REMAP)
UFFD_FEATURE_EVENT_REMAP | \
UFFD_FEATURE_EVENT_MADVDONTNEED)
#define UFFD_API_IOCTLS \
((__u64)1 << _UFFDIO_REGISTER | \
(__u64)1 << _UFFDIO_UNREGISTER | \
Expand Down Expand Up @@ -83,6 +84,11 @@ struct uffd_msg {
__u64 len;
} remap;

struct {
__u64 start;
__u64 end;
} madv_dn;

struct {
/* unused reserved fields */
__u64 reserved1;
Expand All @@ -98,6 +104,7 @@ struct uffd_msg {
#define UFFD_EVENT_PAGEFAULT 0x12
#define UFFD_EVENT_FORK 0x13
#define UFFD_EVENT_REMAP 0x14
#define UFFD_EVENT_MADVDONTNEED 0x15

/* flags for UFFD_EVENT_PAGEFAULT */
#define UFFD_PAGEFAULT_FLAG_WRITE (1<<0) /* If this was a write fault */
Expand All @@ -119,6 +126,7 @@ struct uffdio_api {
#define UFFD_FEATURE_PAGEFAULT_FLAG_WP (1<<0)
#define UFFD_FEATURE_EVENT_FORK (1<<1)
#define UFFD_FEATURE_EVENT_REMAP (1<<2)
#define UFFD_FEATURE_EVENT_MADVDONTNEED (1<<3)
__u64 features;

__u64 ioctls;
Expand Down
2 changes: 2 additions & 0 deletions mm/madvise.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/syscalls.h>
#include <linux/mempolicy.h>
#include <linux/page-isolation.h>
#include <linux/userfaultfd_k.h>
#include <linux/hugetlb.h>
#include <linux/falloc.h>
#include <linux/sched.h>
Expand Down Expand Up @@ -477,6 +478,7 @@ static long madvise_dontneed(struct vm_area_struct *vma,
return -EINVAL;

zap_page_range(vma, start, end - start, NULL);
madvise_userfault_dontneed(vma, prev, start, end);
return 0;
}

Expand Down

0 comments on commit 05ce772

Please sign in to comment.