perf top: Add overwrite fall back
[linux-2.6-microblaze.git] / fs / userfaultfd.c
index 41a75f9..cec550c 100644 (file)
@@ -294,10 +294,13 @@ static inline bool userfaultfd_must_wait(struct userfaultfd_ctx *ctx,
         * pmd_trans_unstable) of the pmd.
         */
        _pmd = READ_ONCE(*pmd);
-       if (!pmd_present(_pmd))
+       if (pmd_none(_pmd))
                goto out;
 
        ret = false;
+       if (!pmd_present(_pmd))
+               goto out;
+
        if (pmd_trans_huge(_pmd))
                goto out;
 
@@ -480,7 +483,7 @@ int handle_userfault(struct vm_fault *vmf, unsigned long reason)
        if (likely(must_wait && !READ_ONCE(ctx->released) &&
                   (return_to_userland ? !signal_pending(current) :
                    !fatal_signal_pending(current)))) {
-               wake_up_poll(&ctx->fd_wqh, POLLIN);
+               wake_up_poll(&ctx->fd_wqh, EPOLLIN);
                schedule();
                ret |= VM_FAULT_MAJOR;
 
@@ -611,7 +614,7 @@ static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
 
                spin_unlock(&ctx->event_wqh.lock);
 
-               wake_up_poll(&ctx->fd_wqh, POLLIN);
+               wake_up_poll(&ctx->fd_wqh, EPOLLIN);
                schedule();
 
                spin_lock(&ctx->event_wqh.lock);
@@ -901,7 +904,7 @@ wakeup:
        /* Flush pending events that may still wait on event_wqh */
        wake_up_all(&ctx->event_wqh);
 
-       wake_up_poll(&ctx->fd_wqh, POLLHUP);
+       wake_up_poll(&ctx->fd_wqh, EPOLLHUP);
        userfaultfd_ctx_put(ctx);
        return 0;
 }
@@ -937,23 +940,23 @@ static inline struct userfaultfd_wait_queue *find_userfault_evt(
        return find_userfault_in(&ctx->event_wqh);
 }
 
-static unsigned int userfaultfd_poll(struct file *file, poll_table *wait)
+static __poll_t userfaultfd_poll(struct file *file, poll_table *wait)
 {
        struct userfaultfd_ctx *ctx = file->private_data;
-       unsigned int ret;
+       __poll_t ret;
 
        poll_wait(file, &ctx->fd_wqh, wait);
 
        switch (ctx->state) {
        case UFFD_STATE_WAIT_API:
-               return POLLERR;
+               return EPOLLERR;
        case UFFD_STATE_RUNNING:
                /*
                 * poll() never guarantees that read won't block.
                 * userfaults can be waken before they're read().
                 */
                if (unlikely(!(file->f_flags & O_NONBLOCK)))
-                       return POLLERR;
+                       return EPOLLERR;
                /*
                 * lockless access to see if there are pending faults
                 * __pollwait last action is the add_wait_queue but
@@ -967,14 +970,14 @@ static unsigned int userfaultfd_poll(struct file *file, poll_table *wait)
                ret = 0;
                smp_mb();
                if (waitqueue_active(&ctx->fault_pending_wqh))
-                       ret = POLLIN;
+                       ret = EPOLLIN;
                else if (waitqueue_active(&ctx->event_wqh))
-                       ret = POLLIN;
+                       ret = EPOLLIN;
 
                return ret;
        default:
                WARN_ON_ONCE(1);
-               return POLLERR;
+               return EPOLLERR;
        }
 }
 
@@ -985,24 +988,14 @@ static int resolve_userfault_fork(struct userfaultfd_ctx *ctx,
                                  struct uffd_msg *msg)
 {
        int fd;
-       struct file *file;
-       unsigned int flags = new->flags & UFFD_SHARED_FCNTL_FLAGS;
 
-       fd = get_unused_fd_flags(flags);
+       fd = anon_inode_getfd("[userfaultfd]", &userfaultfd_fops, new,
+                             O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS));
        if (fd < 0)
                return fd;
 
-       file = anon_inode_getfile("[userfaultfd]", &userfaultfd_fops, new,
-                                 O_RDWR | flags);
-       if (IS_ERR(file)) {
-               put_unused_fd(fd);
-               return PTR_ERR(file);
-       }
-
-       fd_install(fd, file);
        msg->arg.reserved.reserved1 = 0;
        msg->arg.fork.ufd = fd;
-
        return 0;
 }
 
@@ -1884,24 +1877,10 @@ static void init_once_userfaultfd_ctx(void *mem)
        seqcount_init(&ctx->refile_seq);
 }
 
-/**
- * userfaultfd_file_create - Creates a userfaultfd file pointer.
- * @flags: Flags for the userfaultfd file.
- *
- * This function creates a userfaultfd file pointer, w/out installing
- * it into the fd table. This is useful when the userfaultfd file is
- * used during the initialization of data structures that require
- * extra setup after the userfaultfd creation. So the userfaultfd
- * creation is split into the file pointer creation phase, and the
- * file descriptor installation phase.  In this way races with
- * userspace closing the newly installed file descriptor can be
- * avoided.  Returns a userfaultfd file pointer, or a proper error
- * pointer.
- */
-static struct file *userfaultfd_file_create(int flags)
+SYSCALL_DEFINE1(userfaultfd, int, flags)
 {
-       struct file *file;
        struct userfaultfd_ctx *ctx;
+       int fd;
 
        BUG_ON(!current->mm);
 
@@ -1909,14 +1888,12 @@ static struct file *userfaultfd_file_create(int flags)
        BUILD_BUG_ON(UFFD_CLOEXEC != O_CLOEXEC);
        BUILD_BUG_ON(UFFD_NONBLOCK != O_NONBLOCK);
 
-       file = ERR_PTR(-EINVAL);
        if (flags & ~UFFD_SHARED_FCNTL_FLAGS)
-               goto out;
+               return -EINVAL;
 
-       file = ERR_PTR(-ENOMEM);
        ctx = kmem_cache_alloc(userfaultfd_ctx_cachep, GFP_KERNEL);
        if (!ctx)
-               goto out;
+               return -ENOMEM;
 
        atomic_set(&ctx->refcount, 1);
        ctx->flags = flags;
@@ -1927,39 +1904,13 @@ static struct file *userfaultfd_file_create(int flags)
        /* prevent the mm struct to be freed */
        mmgrab(ctx->mm);
 
-       file = anon_inode_getfile("[userfaultfd]", &userfaultfd_fops, ctx,
-                                 O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS));
-       if (IS_ERR(file)) {
+       fd = anon_inode_getfd("[userfaultfd]", &userfaultfd_fops, ctx,
+                             O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS));
+       if (fd < 0) {
                mmdrop(ctx->mm);
                kmem_cache_free(userfaultfd_ctx_cachep, ctx);
        }
-out:
-       return file;
-}
-
-SYSCALL_DEFINE1(userfaultfd, int, flags)
-{
-       int fd, error;
-       struct file *file;
-
-       error = get_unused_fd_flags(flags & UFFD_SHARED_FCNTL_FLAGS);
-       if (error < 0)
-               return error;
-       fd = error;
-
-       file = userfaultfd_file_create(flags);
-       if (IS_ERR(file)) {
-               error = PTR_ERR(file);
-               goto err_put_unused_fd;
-       }
-       fd_install(fd, file);
-
        return fd;
-
-err_put_unused_fd:
-       put_unused_fd(fd);
-
-       return error;
 }
 
 static int __init userfaultfd_init(void)