return __copy_page(ufd, offset, false);
 }
 
+static int uffd_read_msg(int ufd, struct uffd_msg *msg)
+{
+       int ret = read(uffd, msg, sizeof(*msg));
+
+       if (ret != sizeof(*msg)) {
+               if (ret < 0) {
+                       if (errno == EAGAIN)
+                               return 1;
+                       else
+                               perror("blocking read error"), exit(1);
+               } else {
+                       fprintf(stderr, "short read\n"), exit(1);
+               }
+       }
+
+       return 0;
+}
+
+/* Return 1 if page fault handled by us; otherwise 0 */
+static int uffd_handle_page_fault(struct uffd_msg *msg)
+{
+       unsigned long offset;
+
+       if (msg->event != UFFD_EVENT_PAGEFAULT)
+               fprintf(stderr, "unexpected msg event %u\n",
+                       msg->event), exit(1);
+
+       if (bounces & BOUNCE_VERIFY &&
+           msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)
+               fprintf(stderr, "unexpected write fault\n"), exit(1);
+
+       offset = (char *)(unsigned long)msg->arg.pagefault.address - area_dst;
+       offset &= ~(page_size-1);
+
+       return copy_page(uffd, offset);
+}
+
 static void *uffd_poll_thread(void *arg)
 {
        unsigned long cpu = (unsigned long) arg;
        struct uffd_msg msg;
        struct uffdio_register uffd_reg;
        int ret;
-       unsigned long offset;
        char tmp_chr;
        unsigned long userfaults = 0;
 
                if (!(pollfd[0].revents & POLLIN))
                        fprintf(stderr, "pollfd[0].revents %d\n",
                                pollfd[0].revents), exit(1);
-               ret = read(uffd, &msg, sizeof(msg));
-               if (ret < 0) {
-                       if (errno == EAGAIN)
-                               continue;
-                       perror("nonblocking read error"), exit(1);
-               }
+               if (uffd_read_msg(uffd, &msg))
+                       continue;
                switch (msg.event) {
                default:
                        fprintf(stderr, "unexpected msg event %u\n",
                                msg.event), exit(1);
                        break;
                case UFFD_EVENT_PAGEFAULT:
-                       if (msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)
-                               fprintf(stderr, "unexpected write fault\n"), exit(1);
-                       offset = (char *)(unsigned long)msg.arg.pagefault.address -
-                               area_dst;
-                       offset &= ~(page_size-1);
-                       if (copy_page(uffd, offset))
-                               userfaults++;
+                       userfaults += uffd_handle_page_fault(&msg);
                        break;
                case UFFD_EVENT_FORK:
                        close(uffd);
 {
        unsigned long *this_cpu_userfaults;
        struct uffd_msg msg;
-       unsigned long offset;
-       int ret;
 
        this_cpu_userfaults = (unsigned long *) arg;
        *this_cpu_userfaults = 0;
        /* from here cancellation is ok */
 
        for (;;) {
-               ret = read(uffd, &msg, sizeof(msg));
-               if (ret != sizeof(msg)) {
-                       if (ret < 0)
-                               perror("blocking read error"), exit(1);
-                       else
-                               fprintf(stderr, "short read\n"), exit(1);
-               }
-               if (msg.event != UFFD_EVENT_PAGEFAULT)
-                       fprintf(stderr, "unexpected msg event %u\n",
-                               msg.event), exit(1);
-               if (bounces & BOUNCE_VERIFY &&
-                   msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)
-                       fprintf(stderr, "unexpected write fault\n"), exit(1);
-               offset = (char *)(unsigned long)msg.arg.pagefault.address -
-                        area_dst;
-               offset &= ~(page_size-1);
-               if (copy_page(uffd, offset))
-                       (*this_cpu_userfaults)++;
+               if (uffd_read_msg(uffd, &msg))
+                       continue;
+               (*this_cpu_userfaults) += uffd_handle_page_fault(&msg);
        }
        return (void *)NULL;
 }