From: Isaku Yamahata <isaku.yamahata@xxxxxxxxx> Add text cases for guest_memfd KVM_GUEST_MEMORY_FAILURE ioctl. + ioctl(KVM_GUEST_MEMORY_FAILURE) success with backing pages + ioctl(KVM_GUEST_MEMORY_FAILURE) fails with ENOENT without backing page + interaction with fallocate(PUNCH_HOLE) Signed-off-by: Isaku Yamahata <isaku.yamahata@xxxxxxxxx> --- .../testing/selftests/kvm/guest_memfd_test.c | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c b/tools/testing/selftests/kvm/guest_memfd_test.c index d5b4bfcdc3fe..f8b242c9319d 100644 --- a/tools/testing/selftests/kvm/guest_memfd_test.c +++ b/tools/testing/selftests/kvm/guest_memfd_test.c @@ -122,6 +122,53 @@ static void test_fallocate_fail(int fd, size_t page_size, size_t total_size) } } +static void test_memory_failure(int fd, size_t page_size, size_t total_size) +{ + struct kvm_guest_memory_failure mf; + int ret; + int i; + + /* Make whole file unallocated as known initial state */ + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, + 0, total_size); + TEST_ASSERT(!ret, "fallocate(PUNCH_HOLE) at while file should succeed"); + + /* Because there is no backing page, fail to inject memory failure. */ + for (i = 0; i < total_size / page_size; i++) { + mf = (struct kvm_guest_memory_failure) { + .offset = i * page_size, + }; + + ret = ioctl(fd, KVM_GUEST_MEMORY_FAILURE, &mf); + if (ret == -1 && errno == EPERM) { + pr_info("KVM_GUEST_MEMORY_FAILURE requires CAP_SYS_ADMIN. Skipping.\n") + return; + } + TEST_ASSERT(ret == -1 && errno == ENOENT, + "ioctl(KVM_GUEST_MEMORY_FAILURE) should fail i %d", i); + } + + /* Allocate pages with index one and two. */ + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE, page_size, page_size * 2); + TEST_ASSERT(!ret, "fallocate beginning at page_size should succeed"); + + for (i = 0; i < total_size / page_size; i++) { + mf = (struct kvm_guest_memory_failure) { + .offset = i * page_size, + }; + + ret = ioctl(fd, KVM_GUEST_MEMORY_FAILURE, &mf); + + if (i == 1 || i == 2) { + TEST_ASSERT(!ret || (ret == -1 && errno == EBUSY), + "ioctl(KVM_GUEST_MEMORY_FAILURE) should succeed i %d", i); + } else { + TEST_ASSERT(ret == -1 && errno == ENOENT, + "ioctl(KVM_GUEST_MEMORY_FAILURE) should fail i %d", i); + } + } +} + static void test_create_guest_memfd_invalid(struct kvm_vm *vm) { uint64_t valid_flags = 0; @@ -192,6 +239,7 @@ int main(int argc, char *argv[]) test_file_size(fd, page_size, total_size); test_fallocate(fd, page_size, total_size); test_fallocate_fail(fd, page_size, total_size); + test_memory_failure(fd, page_size, total_size); close(fd); } -- 2.25.1