All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anish Moorthy <amoorthy@google.com>
To: seanjc@google.com, oliver.upton@linux.dev, kvm@vger.kernel.org,
	kvmarm@lists.linux.dev
Cc: pbonzini@redhat.com, maz@kernel.org, robert.hoo.linux@gmail.com,
	jthoughton@google.com, amoorthy@google.com, ricarkol@google.com,
	axelrasmussen@google.com, peterx@redhat.com,
	nadav.amit@gmail.com, isaku.yamahata@gmail.com,
	kconsul@linux.vnet.ibm.com
Subject: [PATCH v5 15/17] KVM: selftests: Use EPOLL in userfaultfd_util reader threads and signal errors via TEST_ASSERT
Date: Fri,  8 Sep 2023 22:29:02 +0000	[thread overview]
Message-ID: <20230908222905.1321305-16-amoorthy@google.com> (raw)
In-Reply-To: <20230908222905.1321305-1-amoorthy@google.com>

With multiple reader threads POLLing a single UFFD, the test suffers
from the thundering herd problem: performance degrades as the number of
reader threads is increased. Solve this issue [1] by switching the
the polling mechanism to EPOLL + EPOLLEXCLUSIVE.

Also, change the error-handling convention of uffd_handler_thread_fn.
Instead of just printing errors and returning early from the polling
loop, check for them via TEST_ASSERT. "return NULL" is reserved for a
successful exit from uffd_handler_thread_fn, ie one triggered by a
write to the exit pipe.

Performance samples generated by the command in [2] are given below.

Num Reader Threads, Paging Rate (POLL), Paging Rate (EPOLL)
1      249k      185k
2      201k      235k
4      186k      155k
16     150k      217k
32     89k       198k

[1] Single-vCPU performance does suffer somewhat.
[2] ./demand_paging_test -u MINOR -s shmem -v 4 -o -r <num readers>

Signed-off-by: Anish Moorthy <amoorthy@google.com>
Acked-by: James Houghton <jthoughton@google.com>
---
 .../selftests/kvm/demand_paging_test.c        |  1 -
 .../selftests/kvm/lib/userfaultfd_util.c      | 74 +++++++++----------
 2 files changed, 35 insertions(+), 40 deletions(-)

diff --git a/tools/testing/selftests/kvm/demand_paging_test.c b/tools/testing/selftests/kvm/demand_paging_test.c
index f7897a951f90..0455347f932a 100644
--- a/tools/testing/selftests/kvm/demand_paging_test.c
+++ b/tools/testing/selftests/kvm/demand_paging_test.c
@@ -13,7 +13,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
-#include <poll.h>
 #include <pthread.h>
 #include <linux/userfaultfd.h>
 #include <sys/syscall.h>
diff --git a/tools/testing/selftests/kvm/lib/userfaultfd_util.c b/tools/testing/selftests/kvm/lib/userfaultfd_util.c
index 6f220aa4fb08..2a179133645a 100644
--- a/tools/testing/selftests/kvm/lib/userfaultfd_util.c
+++ b/tools/testing/selftests/kvm/lib/userfaultfd_util.c
@@ -16,6 +16,7 @@
 #include <poll.h>
 #include <pthread.h>
 #include <linux/userfaultfd.h>
+#include <sys/epoll.h>
 #include <sys/syscall.h>
 
 #include "kvm_util.h"
@@ -32,60 +33,55 @@ static void *uffd_handler_thread_fn(void *arg)
 	int64_t pages = 0;
 	struct timespec start;
 	struct timespec ts_diff;
+	int epollfd;
+	struct epoll_event evt;
+
+	epollfd = epoll_create(1);
+	TEST_ASSERT(epollfd >= 0, "Failed to create epollfd.");
+
+	evt.events = EPOLLIN | EPOLLEXCLUSIVE;
+	evt.data.u32 = 0;
+	TEST_ASSERT(epoll_ctl(epollfd, EPOLL_CTL_ADD, uffd, &evt) == 0,
+		    "Failed to add uffd to epollfd");
+
+	evt.events = EPOLLIN;
+	evt.data.u32 = 1;
+	TEST_ASSERT(epoll_ctl(epollfd, EPOLL_CTL_ADD, reader_args->pipe, &evt) == 0,
+		    "Failed to add pipe to epollfd");
 
 	clock_gettime(CLOCK_MONOTONIC, &start);
 	while (1) {
 		struct uffd_msg msg;
-		struct pollfd pollfd[2];
-		char tmp_chr;
 		int r;
 
-		pollfd[0].fd = uffd;
-		pollfd[0].events = POLLIN;
-		pollfd[1].fd = reader_args->pipe;
-		pollfd[1].events = POLLIN;
-
-		r = poll(pollfd, 2, -1);
-		switch (r) {
-		case -1:
-			pr_info("poll err");
-			continue;
-		case 0:
-			continue;
-		case 1:
-			break;
-		default:
-			pr_info("Polling uffd returned %d", r);
-			return NULL;
-		}
+		r = epoll_wait(epollfd, &evt, 1, -1);
+		TEST_ASSERT(r == 1,
+			    "Unexpected number of events (%d) from epoll, errno = %d",
+			    r, errno);
 
-		if (pollfd[0].revents & POLLERR) {
-			pr_info("uffd revents has POLLERR");
-			return NULL;
-		}
+		if (evt.data.u32 == 1) {
+			char tmp_chr;
 
-		if (pollfd[1].revents & POLLIN) {
-			r = read(pollfd[1].fd, &tmp_chr, 1);
+			TEST_ASSERT(!(evt.events & (EPOLLERR | EPOLLHUP)),
+				    "Reader thread received EPOLLERR or EPOLLHUP on pipe.");
+			r = read(reader_args->pipe, &tmp_chr, 1);
 			TEST_ASSERT(r == 1,
-				    "Error reading pipefd in UFFD thread\n");
+				    "Error reading pipefd in uffd reader thread");
 			break;
 		}
 
-		if (!(pollfd[0].revents & POLLIN))
-			continue;
+		TEST_ASSERT(!(evt.events & (EPOLLERR | EPOLLHUP)),
+			    "Reader thread received EPOLLERR or EPOLLHUP on uffd.");
 
 		r = read(uffd, &msg, sizeof(msg));
 		if (r == -1) {
-			if (errno == EAGAIN)
-				continue;
-			pr_info("Read of uffd got errno %d\n", errno);
-			return NULL;
+			TEST_ASSERT(errno == EAGAIN,
+				    "Error reading from UFFD: errno = %d", errno);
+			continue;
 		}
 
-		if (r != sizeof(msg)) {
-			pr_info("Read on uffd returned unexpected size: %d bytes", r);
-			return NULL;
-		}
+		TEST_ASSERT(r == sizeof(msg),
+			    "Read on uffd returned unexpected number of bytes (%d)", r);
 
 		if (!(msg.event & UFFD_EVENT_PAGEFAULT))
 			continue;
@@ -93,8 +89,8 @@ static void *uffd_handler_thread_fn(void *arg)
 		if (reader_args->delay)
 			usleep(reader_args->delay);
 		r = reader_args->handler(reader_args->uffd_mode, uffd, &msg);
-		if (r < 0)
-			return NULL;
+		TEST_ASSERT(r >= 0,
+			    "Reader thread handler fn returned negative value %d", r);
 		pages++;
 	}
 
-- 
2.42.0.283.g2d96d420d3-goog


  parent reply	other threads:[~2023-09-08 22:30 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-08 22:28 [PATCH v5 00/17] Improve KVM + userfaultfd live migration via annotated memory faults Anish Moorthy
2023-09-08 22:28 ` [PATCH v5 01/17] KVM: Clarify documentation of hva_to_pfn()'s 'atomic' parameter Anish Moorthy
2023-09-08 22:28 ` [PATCH v5 02/17] KVM: Add docstrings to __kvm_read/write_guest_page() Anish Moorthy
2023-10-05  1:18   ` Sean Christopherson
2023-09-08 22:28 ` [PATCH v5 03/17] KVM: Simplify error handling in __gfn_to_pfn_memslot() Anish Moorthy
2023-09-08 22:28 ` [PATCH v5 04/17] KVM: Add KVM_CAP_MEMORY_FAULT_INFO Anish Moorthy
2023-10-05  1:14   ` Sean Christopherson
2023-10-05 18:45     ` Anish Moorthy
2023-10-05 22:13       ` Sean Christopherson
2023-10-10 22:58   ` David Matlack
2023-10-10 23:40     ` Sean Christopherson
2023-10-16 17:07       ` David Matlack
2023-10-16 19:14         ` Sean Christopherson
2023-09-08 22:28 ` [PATCH v5 05/17] KVM: Annotate -EFAULTs from kvm_vcpu_read/write_guest_page() Anish Moorthy
2023-09-14  8:04   ` kernel test robot
2023-10-05  1:53   ` Sean Christopherson
2023-10-05 23:03   ` Anish Moorthy
2023-09-08 22:28 ` [PATCH v5 06/17] KVM: x86: Annotate -EFAULTs from kvm_handle_error_pfn() Anish Moorthy
2023-10-05  1:26   ` Sean Christopherson
2023-10-05 23:57     ` Anish Moorthy
2023-10-06  0:36       ` Sean Christopherson
2023-09-08 22:28 ` [PATCH v5 07/17] KVM: arm64: Annotate -EFAULT from user_mem_abort() Anish Moorthy
2023-09-28 21:42   ` Anish Moorthy
2023-10-05  1:26   ` Sean Christopherson
2023-10-10 23:01   ` David Matlack
2023-09-08 22:28 ` [PATCH v5 08/17] KVM: Allow hva_pfn_fast() to resolve read faults Anish Moorthy
2023-09-08 22:28 ` [PATCH v5 09/17] KVM: Introduce KVM_CAP_USERFAULT_ON_MISSING without implementation Anish Moorthy
2023-10-10 23:16   ` David Matlack
2023-10-11 17:54     ` Anish Moorthy
2023-10-16 19:38       ` Sean Christopherson
2023-09-08 22:28 ` [PATCH v5 10/17] KVM: Implement KVM_CAP_USERFAULT_ON_MISSING by atomizing __gfn_to_pfn_memslot() calls Anish Moorthy
2023-10-05  1:44   ` Sean Christopherson
2023-10-05 18:58     ` Anish Moorthy
2023-10-06  0:17       ` Sean Christopherson
2023-10-11 22:04         ` Anish Moorthy
2023-11-01 21:53     ` Anish Moorthy
2023-11-01 22:03       ` Sean Christopherson
2023-11-01 22:25         ` Anish Moorthy
2023-11-01 22:39           ` David Matlack
2023-11-01 22:42           ` Sean Christopherson
2023-11-02 19:14       ` Anish Moorthy
2023-11-02 20:25         ` Anish Moorthy
2023-11-03 20:05         ` Sean Christopherson
2023-09-08 22:28 ` [PATCH v5 11/17] KVM: x86: Enable KVM_CAP_USERFAULT_ON_MISSING Anish Moorthy
2023-10-05  1:52   ` Sean Christopherson
2023-11-01 22:55     ` Anish Moorthy
2023-11-02 14:31       ` Sean Christopherson
2023-09-08 22:28 ` [PATCH v5 12/17] KVM: arm64: " Anish Moorthy
2023-09-08 22:29 ` [PATCH v5 13/17] KVM: selftests: Report per-vcpu demand paging rate from demand paging test Anish Moorthy
2023-09-08 22:29 ` [PATCH v5 14/17] KVM: selftests: Allow many vCPUs and reader threads per UFFD in " Anish Moorthy
2023-09-08 22:29 ` Anish Moorthy [this message]
2023-09-08 22:29 ` [PATCH v5 16/17] KVM: selftests: Add memslot_flags parameter to memstress_create_vm() Anish Moorthy
2023-09-08 22:29 ` [PATCH v5 17/17] KVM: selftests: Handle memory fault exits in demand_paging_test Anish Moorthy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230908222905.1321305-16-amoorthy@google.com \
    --to=amoorthy@google.com \
    --cc=axelrasmussen@google.com \
    --cc=isaku.yamahata@gmail.com \
    --cc=jthoughton@google.com \
    --cc=kconsul@linux.vnet.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.linux.dev \
    --cc=maz@kernel.org \
    --cc=nadav.amit@gmail.com \
    --cc=oliver.upton@linux.dev \
    --cc=pbonzini@redhat.com \
    --cc=peterx@redhat.com \
    --cc=ricarkol@google.com \
    --cc=robert.hoo.linux@gmail.com \
    --cc=seanjc@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.