diff --git a/kvm-multifd-Create-property-multifd-flush-after-each-sec.patch b/kvm-multifd-Create-property-multifd-flush-after-each-sec.patch new file mode 100644 index 0000000..0bebd2e --- /dev/null +++ b/kvm-multifd-Create-property-multifd-flush-after-each-sec.patch @@ -0,0 +1,127 @@ +From 2a5ea92ca0a5dffad54e4d06a683f683996cea9a Mon Sep 17 00:00:00 2001 +From: Juan Quintela +Date: Tue, 21 Jun 2022 12:13:14 +0200 +Subject: [PATCH 05/12] multifd: Create property + multifd-flush-after-each-section +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: quintela1 +RH-MergeRequest: 186: Multifd flushes its channels 10 times per second +RH-Bugzilla: 2196295 +RH-Acked-by: Peter Xu +RH-Acked-by: Leonardo Brás +RH-Commit: [1/3] 5bf5348e8be5b1d1629b859ce1ddb7aa0d72c0d6 (juan.quintela/c9s-qemu-kvm) + +We used to flush all channels at the end of each RAM section +sent. That is not needed, so preparing to only flush after a full +iteration through all the RAM. + +Default value of the property is false. But we return "true" in +migrate_multifd_flush_after_each_section() until we implement the code +in following patches. + +Signed-off-by: Juan Quintela +Reviewed-by: Dr. David Alan Gilbert +Acked-by: Peter Xu + +--- + +Rename each-iteration to after-each-section +Rename multifd-sync-after-each-section to + multifd-flush-after-each-section +Move to machine-8.0 (peter) + +conflit hw_compat_8_0 and hw_compat_rhel_9_2 + +(cherry picked from commit 77c259a4cb1c9799754b48f570301ebf1de5ded8) +--- + hw/core/machine.c | 2 ++ + migration/migration.h | 12 ++++++++++++ + migration/options.c | 13 +++++++++++++ + migration/options.h | 1 + + 4 files changed, 28 insertions(+) + +diff --git a/hw/core/machine.c b/hw/core/machine.c +index 5abdc8c39b..5ea52317b9 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -54,6 +54,8 @@ const char *rhel_old_machine_deprecation = + "machine types for previous major releases are deprecated"; + + GlobalProperty hw_compat_rhel_9_2[] = { ++ /* hw_compat_rhel_9_2 from hw_compat_8_0 */ ++ { "migration", "multifd-flush-after-each-section", "on"}, + /* hw_compat_rhel_9_2 from hw_compat_7_2 */ + { "e1000e", "migrate-timadj", "off" }, + /* hw_compat_rhel_9_2 from hw_compat_7_2 */ +diff --git a/migration/migration.h b/migration/migration.h +index 7ccf460aa2..04c78c1fd6 100644 +--- a/migration/migration.h ++++ b/migration/migration.h +@@ -411,6 +411,18 @@ struct MigrationState { + */ + bool preempt_pre_7_2; + ++ /* ++ * flush every channel after each section sent. ++ * ++ * This assures that we can't mix pages from one iteration through ++ * ram pages with pages for the following iteration. We really ++ * only need to do this flush after we have go through all the ++ * dirty pages. For historical reasons, we do that after each ++ * section. This is suboptimal (we flush too many times). ++ * Default value is false. Setting this property has no effect ++ * until the patch that removes this comment. (since 8.1) ++ */ ++ bool multifd_flush_after_each_section; + /* + * This decides the size of guest memory chunk that will be used + * to track dirty bitmap clearing. The size of memory chunk will +diff --git a/migration/options.c b/migration/options.c +index ccd7ef3907..5b0d080ecb 100644 +--- a/migration/options.c ++++ b/migration/options.c +@@ -88,6 +88,8 @@ Property migration_properties[] = { + send_section_footer, true), + DEFINE_PROP_BOOL("decompress-error-check", MigrationState, + decompress_error_check, true), ++ DEFINE_PROP_BOOL("multifd-flush-after-each-section", MigrationState, ++ multifd_flush_after_each_section, true), + DEFINE_PROP_UINT8("x-clear-bitmap-shift", MigrationState, + clear_bitmap_shift, CLEAR_BITMAP_SHIFT_DEFAULT), + DEFINE_PROP_BOOL("x-preempt-pre-7-2", MigrationState, +@@ -344,6 +346,17 @@ bool migrate_zero_copy_send(void) + + /* pseudo capabilities */ + ++bool migrate_multifd_flush_after_each_section(void) ++{ ++ MigrationState *s = migrate_get_current(); ++ ++ /* ++ * Until the patch that remove this comment, we always return that ++ * the property is enabled. ++ */ ++ return true || s->multifd_flush_after_each_section; ++} ++ + bool migrate_postcopy(void) + { + return migrate_postcopy_ram() || migrate_dirty_bitmaps(); +diff --git a/migration/options.h b/migration/options.h +index 0fc7be6869..271f49ae5f 100644 +--- a/migration/options.h ++++ b/migration/options.h +@@ -60,6 +60,7 @@ bool migrate_zero_copy_send(void); + * check, but they are not a capability. + */ + ++bool migrate_multifd_flush_after_each_section(void); + bool migrate_postcopy(void); + bool migrate_tls(void); + +-- +2.39.3 + diff --git a/kvm-multifd-Only-flush-once-each-full-round-of-memory.patch b/kvm-multifd-Only-flush-once-each-full-round-of-memory.patch new file mode 100644 index 0000000..3f76384 --- /dev/null +++ b/kvm-multifd-Only-flush-once-each-full-round-of-memory.patch @@ -0,0 +1,166 @@ +From e6f770506091eada46c63ac1c8b934b508e3807f Mon Sep 17 00:00:00 2001 +From: Juan Quintela +Date: Tue, 21 Jun 2022 13:36:11 +0200 +Subject: [PATCH 07/12] multifd: Only flush once each full round of memory +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: quintela1 +RH-MergeRequest: 186: Multifd flushes its channels 10 times per second +RH-Bugzilla: 2196295 +RH-Acked-by: Peter Xu +RH-Acked-by: Leonardo Brás +RH-Commit: [3/3] 33f76dfc72a2552a42dc7f0fe3923564185a7bf7 (juan.quintela/c9s-qemu-kvm) + +We need to add a new flag to mean to flush at that point. +Notice that we still flush at the end of setup and at the end of +complete stages. + +Signed-off-by: Juan Quintela +Acked-by: Peter Xu + +--- + +Add missing qemu_fflush(), now it passes all tests always. +In the previous version, the check that changes the default value to +false got lost in some rebase. Get it back. + +(cherry picked from commit 294e5a4034e81b3d8db03b4e0f691386f20d6ed3) +--- + migration/migration.h | 3 +-- + migration/options.c | 8 ++------ + migration/ram.c | 28 +++++++++++++++++++++++++++- + 3 files changed, 30 insertions(+), 9 deletions(-) + +diff --git a/migration/migration.h b/migration/migration.h +index 04c78c1fd6..dfec649af8 100644 +--- a/migration/migration.h ++++ b/migration/migration.h +@@ -419,8 +419,7 @@ struct MigrationState { + * only need to do this flush after we have go through all the + * dirty pages. For historical reasons, we do that after each + * section. This is suboptimal (we flush too many times). +- * Default value is false. Setting this property has no effect +- * until the patch that removes this comment. (since 8.1) ++ * Default value is false. (since 8.1) + */ + bool multifd_flush_after_each_section; + /* +diff --git a/migration/options.c b/migration/options.c +index 5b0d080ecb..e13c7cb8e5 100644 +--- a/migration/options.c ++++ b/migration/options.c +@@ -89,7 +89,7 @@ Property migration_properties[] = { + DEFINE_PROP_BOOL("decompress-error-check", MigrationState, + decompress_error_check, true), + DEFINE_PROP_BOOL("multifd-flush-after-each-section", MigrationState, +- multifd_flush_after_each_section, true), ++ multifd_flush_after_each_section, false), + DEFINE_PROP_UINT8("x-clear-bitmap-shift", MigrationState, + clear_bitmap_shift, CLEAR_BITMAP_SHIFT_DEFAULT), + DEFINE_PROP_BOOL("x-preempt-pre-7-2", MigrationState, +@@ -350,11 +350,7 @@ bool migrate_multifd_flush_after_each_section(void) + { + MigrationState *s = migrate_get_current(); + +- /* +- * Until the patch that remove this comment, we always return that +- * the property is enabled. +- */ +- return true || s->multifd_flush_after_each_section; ++ return s->multifd_flush_after_each_section; + } + + bool migrate_postcopy(void) +diff --git a/migration/ram.c b/migration/ram.c +index 1e2414d681..e9dcda8b9d 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -86,6 +86,7 @@ + #define RAM_SAVE_FLAG_XBZRLE 0x40 + /* 0x80 is reserved in qemu-file.h for RAM_SAVE_FLAG_HOOK */ + #define RAM_SAVE_FLAG_COMPRESS_PAGE 0x100 ++#define RAM_SAVE_FLAG_MULTIFD_FLUSH 0x200 + /* We can't use any flag that is bigger than 0x200 */ + + int (*xbzrle_encode_buffer_func)(uint8_t *, uint8_t *, int, +@@ -1581,6 +1582,7 @@ retry: + * associated with the search process. + * + * Returns: ++ * <0: An error happened + * PAGE_ALL_CLEAN: no dirty page found, give up + * PAGE_TRY_AGAIN: no dirty page found, retry for next block + * PAGE_DIRTY_FOUND: dirty page found +@@ -1608,6 +1610,15 @@ static int find_dirty_block(RAMState *rs, PageSearchStatus *pss) + pss->page = 0; + pss->block = QLIST_NEXT_RCU(pss->block, next); + if (!pss->block) { ++ if (!migrate_multifd_flush_after_each_section()) { ++ QEMUFile *f = rs->pss[RAM_CHANNEL_PRECOPY].pss_channel; ++ int ret = multifd_send_sync_main(f); ++ if (ret < 0) { ++ return ret; ++ } ++ qemu_put_be64(f, RAM_SAVE_FLAG_MULTIFD_FLUSH); ++ qemu_fflush(f); ++ } + /* + * If memory migration starts over, we will meet a dirtied page + * which may still exists in compression threads's ring, so we +@@ -2600,6 +2611,9 @@ static int ram_find_and_save_block(RAMState *rs) + break; + } else if (res == PAGE_TRY_AGAIN) { + continue; ++ } else if (res < 0) { ++ pages = res; ++ break; + } + } + } +@@ -3286,6 +3300,10 @@ static int ram_save_setup(QEMUFile *f, void *opaque) + return ret; + } + ++ if (!migrate_multifd_flush_after_each_section()) { ++ qemu_put_be64(f, RAM_SAVE_FLAG_MULTIFD_FLUSH); ++ } ++ + qemu_put_be64(f, RAM_SAVE_FLAG_EOS); + qemu_fflush(f); + +@@ -3471,6 +3489,9 @@ static int ram_save_complete(QEMUFile *f, void *opaque) + return ret; + } + ++ if (!migrate_multifd_flush_after_each_section()) { ++ qemu_put_be64(f, RAM_SAVE_FLAG_MULTIFD_FLUSH); ++ } + qemu_put_be64(f, RAM_SAVE_FLAG_EOS); + qemu_fflush(f); + +@@ -4152,7 +4173,9 @@ int ram_load_postcopy(QEMUFile *f, int channel) + } + decompress_data_with_multi_threads(f, page_buffer, len); + break; +- ++ case RAM_SAVE_FLAG_MULTIFD_FLUSH: ++ multifd_recv_sync_main(); ++ break; + case RAM_SAVE_FLAG_EOS: + /* normal exit */ + if (migrate_multifd_flush_after_each_section()) { +@@ -4426,6 +4449,9 @@ static int ram_load_precopy(QEMUFile *f) + break; + } + break; ++ case RAM_SAVE_FLAG_MULTIFD_FLUSH: ++ multifd_recv_sync_main(); ++ break; + case RAM_SAVE_FLAG_EOS: + /* normal exit */ + if (migrate_multifd_flush_after_each_section()) { +-- +2.39.3 + diff --git a/kvm-multifd-Protect-multifd_send_sync_main-calls.patch b/kvm-multifd-Protect-multifd_send_sync_main-calls.patch new file mode 100644 index 0000000..779841f --- /dev/null +++ b/kvm-multifd-Protect-multifd_send_sync_main-calls.patch @@ -0,0 +1,78 @@ +From c4bfb4900b95e13bef2d86b83c33786c7c4f6289 Mon Sep 17 00:00:00 2001 +From: Juan Quintela +Date: Tue, 21 Jun 2022 12:21:32 +0200 +Subject: [PATCH 06/12] multifd: Protect multifd_send_sync_main() calls +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: quintela1 +RH-MergeRequest: 186: Multifd flushes its channels 10 times per second +RH-Bugzilla: 2196295 +RH-Acked-by: Peter Xu +RH-Acked-by: Leonardo Brás +RH-Commit: [2/3] a91adf59c6b2f39bf4a308f566b00e39cae6e0ae (juan.quintela/c9s-qemu-kvm) + +We only need to do that on the ram_save_iterate() call on sending and +on destination when we get a RAM_SAVE_FLAG_EOS. + +In setup() and complete() we need to synch in both new and old cases, +so don't add a check there. + +Signed-off-by: Juan Quintela +Reviewed-by: Dr. David Alan Gilbert +Acked-by: Peter Xu + +--- + +Remove the wrappers that we take out on patch 5. + +(cherry picked from commit b05292c237030343516d073b1a1e5f49ffc017a8) +--- + migration/ram.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/migration/ram.c b/migration/ram.c +index 01356f60a4..1e2414d681 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -3394,9 +3394,11 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) + out: + if (ret >= 0 + && migration_is_setup_or_active(migrate_get_current()->state)) { +- ret = multifd_send_sync_main(rs->pss[RAM_CHANNEL_PRECOPY].pss_channel); +- if (ret < 0) { +- return ret; ++ if (migrate_multifd_flush_after_each_section()) { ++ ret = multifd_send_sync_main(rs->pss[RAM_CHANNEL_PRECOPY].pss_channel); ++ if (ret < 0) { ++ return ret; ++ } + } + + qemu_put_be64(f, RAM_SAVE_FLAG_EOS); +@@ -4153,7 +4155,9 @@ int ram_load_postcopy(QEMUFile *f, int channel) + + case RAM_SAVE_FLAG_EOS: + /* normal exit */ +- multifd_recv_sync_main(); ++ if (migrate_multifd_flush_after_each_section()) { ++ multifd_recv_sync_main(); ++ } + break; + default: + error_report("Unknown combination of migration flags: 0x%x" +@@ -4424,7 +4428,9 @@ static int ram_load_precopy(QEMUFile *f) + break; + case RAM_SAVE_FLAG_EOS: + /* normal exit */ +- multifd_recv_sync_main(); ++ if (migrate_multifd_flush_after_each_section()) { ++ multifd_recv_sync_main(); ++ } + break; + default: + if (flags & RAM_SAVE_FLAG_HOOK) { +-- +2.39.3 + diff --git a/kvm-net-socket-move-fd-type-checking-to-its-own-function.patch b/kvm-net-socket-move-fd-type-checking-to-its-own-function.patch new file mode 100644 index 0000000..20b9c04 --- /dev/null +++ b/kvm-net-socket-move-fd-type-checking-to-its-own-function.patch @@ -0,0 +1,78 @@ +From d6b3f9e4b388b8d621761104ddf075d6087f6d6c Mon Sep 17 00:00:00 2001 +From: Laurent Vivier +Date: Fri, 9 Jun 2023 09:27:47 +0200 +Subject: [PATCH 09/12] net: socket: move fd type checking to its own function + +RH-Author: Laurent Vivier +RH-MergeRequest: 187: net: socket: do not close file descriptor if it's not a socket +RH-Jira: RHEL-582 +RH-Acked-by: Stefano Brivio +RH-Acked-by: Jason Wang +RH-Acked-by: David Gibson (Red Hat) +RH-Commit: [2/3] 9726f0ae81ac209b5db33dc7767f652867d8ca0a (lvivier/qemu-kvm-centos) + +JIRA: https://issues.redhat.com/browse/RHEL-582 + +Reviewed-by: David Gibson +Signed-off-by: Laurent Vivier +Signed-off-by: Jason Wang +(cherry picked from commit 23455ae341656ca867ee4a171826b9d280d6acb5) +--- + net/socket.c | 28 ++++++++++++++++++++-------- + 1 file changed, 20 insertions(+), 8 deletions(-) + +diff --git a/net/socket.c b/net/socket.c +index 24dcaa55bc..6b1f0fec3a 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -446,16 +446,32 @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer, + return s; + } + ++static int net_socket_fd_check(int fd, Error **errp) ++{ ++ int so_type, optlen = sizeof(so_type); ++ ++ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type, ++ (socklen_t *)&optlen) < 0) { ++ error_setg(errp, "can't get socket option SO_TYPE"); ++ return -1; ++ } ++ if (so_type != SOCK_DGRAM && so_type != SOCK_STREAM) { ++ error_setg(errp, "socket type=%d for fd=%d must be either" ++ " SOCK_DGRAM or SOCK_STREAM", so_type, fd); ++ return -1; ++ } ++ return so_type; ++} ++ + static NetSocketState *net_socket_fd_init(NetClientState *peer, + const char *model, const char *name, + int fd, int is_connected, + const char *mc, Error **errp) + { +- int so_type = -1, optlen=sizeof(so_type); ++ int so_type; + +- if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type, +- (socklen_t *)&optlen)< 0) { +- error_setg(errp, "can't get socket option SO_TYPE"); ++ so_type = net_socket_fd_check(fd, errp); ++ if (so_type < 0) { + close(fd); + return NULL; + } +@@ -465,10 +481,6 @@ static NetSocketState *net_socket_fd_init(NetClientState *peer, + mc, errp); + case SOCK_STREAM: + return net_socket_fd_init_stream(peer, model, name, fd, is_connected); +- default: +- error_setg(errp, "socket type=%d for fd=%d must be either" +- " SOCK_DGRAM or SOCK_STREAM", so_type, fd); +- close(fd); + } + return NULL; + } +-- +2.39.3 + diff --git a/kvm-net-socket-prepare-to-cleanup-net_init_socket.patch b/kvm-net-socket-prepare-to-cleanup-net_init_socket.patch new file mode 100644 index 0000000..269da29 --- /dev/null +++ b/kvm-net-socket-prepare-to-cleanup-net_init_socket.patch @@ -0,0 +1,60 @@ +From a467540e49e76c5961d86e3f47d3f8fcad8cef09 Mon Sep 17 00:00:00 2001 +From: Laurent Vivier +Date: Fri, 9 Jun 2023 09:27:46 +0200 +Subject: [PATCH 08/12] net: socket: prepare to cleanup net_init_socket() + +RH-Author: Laurent Vivier +RH-MergeRequest: 187: net: socket: do not close file descriptor if it's not a socket +RH-Jira: RHEL-582 +RH-Acked-by: Stefano Brivio +RH-Acked-by: Jason Wang +RH-Acked-by: David Gibson (Red Hat) +RH-Commit: [1/3] 3e4f8370586ae1ac2474fef971a239edb31eeb67 (lvivier/qemu-kvm-centos) + +JIRA: https://issues.redhat.com/browse/RHEL-582 + +Use directly net_socket_fd_init_stream() and net_socket_fd_init_dgram() +when the socket type is already known. + +Reviewed-by: David Gibson +Signed-off-by: Laurent Vivier +Signed-off-by: Jason Wang +(cherry picked from commit 006c3fa74c3edb978ff46d2851699e9a95609da5) +--- + net/socket.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/socket.c b/net/socket.c +index ba6e5b0b00..24dcaa55bc 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -587,7 +587,7 @@ static int net_socket_connect_init(NetClientState *peer, + break; + } + } +- s = net_socket_fd_init(peer, model, name, fd, connected, NULL, errp); ++ s = net_socket_fd_init_stream(peer, model, name, fd, connected); + if (!s) { + return -1; + } +@@ -629,7 +629,7 @@ static int net_socket_mcast_init(NetClientState *peer, + return -1; + } + +- s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp); ++ s = net_socket_fd_init_dgram(peer, model, name, fd, 0, NULL, errp); + if (!s) { + return -1; + } +@@ -683,7 +683,7 @@ static int net_socket_udp_init(NetClientState *peer, + } + qemu_socket_set_nonblock(fd); + +- s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp); ++ s = net_socket_fd_init_dgram(peer, model, name, fd, 0, NULL, errp); + if (!s) { + return -1; + } +-- +2.39.3 + diff --git a/kvm-net-socket-remove-net_init_socket.patch b/kvm-net-socket-remove-net_init_socket.patch new file mode 100644 index 0000000..98c96f2 --- /dev/null +++ b/kvm-net-socket-remove-net_init_socket.patch @@ -0,0 +1,102 @@ +From ecb4f97895849c562112b76a30ddc2037e8df79e Mon Sep 17 00:00:00 2001 +From: Laurent Vivier +Date: Fri, 9 Jun 2023 09:27:48 +0200 +Subject: [PATCH 10/12] net: socket: remove net_init_socket() + +RH-Author: Laurent Vivier +RH-MergeRequest: 187: net: socket: do not close file descriptor if it's not a socket +RH-Jira: RHEL-582 +RH-Acked-by: Stefano Brivio +RH-Acked-by: Jason Wang +RH-Acked-by: David Gibson (Red Hat) +RH-Commit: [3/3] e1d7939f5df4a77c2fff62d1ae4899a7a3615ad9 (lvivier/qemu-kvm-centos) + +JIRA: https://issues.redhat.com/browse/RHEL-582 + +Move the file descriptor type checking before doing anything with it. +If it's not usable, don't close it as it could be in use by another +part of QEMU, only fail and report an error. + +Reviewed-by: David Gibson +Signed-off-by: Laurent Vivier +Signed-off-by: Jason Wang +(cherry picked from commit b6aeee02980e193f744f74c48fd900940feb2799) +--- + net/socket.c | 43 +++++++++++++++++-------------------------- + 1 file changed, 17 insertions(+), 26 deletions(-) + +diff --git a/net/socket.c b/net/socket.c +index 6b1f0fec3a..8e3702e1f3 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -463,28 +463,6 @@ static int net_socket_fd_check(int fd, Error **errp) + return so_type; + } + +-static NetSocketState *net_socket_fd_init(NetClientState *peer, +- const char *model, const char *name, +- int fd, int is_connected, +- const char *mc, Error **errp) +-{ +- int so_type; +- +- so_type = net_socket_fd_check(fd, errp); +- if (so_type < 0) { +- close(fd); +- return NULL; +- } +- switch(so_type) { +- case SOCK_DGRAM: +- return net_socket_fd_init_dgram(peer, model, name, fd, is_connected, +- mc, errp); +- case SOCK_STREAM: +- return net_socket_fd_init_stream(peer, model, name, fd, is_connected); +- } +- return NULL; +-} +- + static void net_socket_accept(void *opaque) + { + NetSocketState *s = opaque; +@@ -728,21 +706,34 @@ int net_init_socket(const Netdev *netdev, const char *name, + } + + if (sock->fd) { +- int fd, ret; ++ int fd, ret, so_type; + + fd = monitor_fd_param(monitor_cur(), sock->fd, errp); + if (fd == -1) { + return -1; + } ++ so_type = net_socket_fd_check(fd, errp); ++ if (so_type < 0) { ++ return -1; ++ } + ret = qemu_socket_try_set_nonblock(fd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); + return -1; + } +- if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast, +- errp)) { +- return -1; ++ switch (so_type) { ++ case SOCK_DGRAM: ++ if (!net_socket_fd_init_dgram(peer, "socket", name, fd, 1, ++ sock->mcast, errp)) { ++ return -1; ++ } ++ break; ++ case SOCK_STREAM: ++ if (!net_socket_fd_init_stream(peer, "socket", name, fd, 1)) { ++ return -1; ++ } ++ break; + } + return 0; + } +-- +2.39.3 + diff --git a/kvm-pcie-Add-hotplug-detect-state-register-to-cmask.patch b/kvm-pcie-Add-hotplug-detect-state-register-to-cmask.patch new file mode 100644 index 0000000..1ec1c82 --- /dev/null +++ b/kvm-pcie-Add-hotplug-detect-state-register-to-cmask.patch @@ -0,0 +1,87 @@ +From 2732b6c5ef249d3ec9affca66768cc2fc476ff7c Mon Sep 17 00:00:00 2001 +From: Leonardo Bras +Date: Thu, 6 Jul 2023 01:55:47 -0300 +Subject: [PATCH 11/12] pcie: Add hotplug detect state register to cmask +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Leonardo Brás +RH-MergeRequest: 188: pcie: Add hotplug detect state register to cmask +RH-Bugzilla: 2215819 +RH-Acked-by: Peter Xu +RH-Acked-by: quintela1 +RH-Commit: [1/1] a125fa337711bddbc957c399044393e82272b143 (LeoBras/centos-qemu-kvm) + +When trying to migrate a machine type pc-q35-6.0 or lower, with this +cmdline options, + +-device driver=pcie-root-port,port=18,chassis=19,id=pcie-root-port18,bus=pcie.0,addr=0x12 \ +-device driver=nec-usb-xhci,p2=4,p3=4,id=nex-usb-xhci0,bus=pcie-root-port18,addr=0x12.0x1 + +the following bug happens after all ram pages were sent: + +qemu-kvm: get_pci_config_device: Bad config data: i=0x6e read: 0 device: 40 cmask: ff wmask: 0 w1cmask:19 +qemu-kvm: Failed to load PCIDevice:config +qemu-kvm: Failed to load pcie-root-port:parent_obj.parent_obj.parent_obj +qemu-kvm: error while loading state for instance 0x0 of device '0000:00:12.0/pcie-root-port' +qemu-kvm: load of migration failed: Invalid argument + +This happens on pc-q35-6.0 or lower because of: +{ "ICH9-LPC", ACPI_PM_PROP_ACPI_PCIHP_BRIDGE, "off" } + +In this scenario, hotplug_handler_plug() calls pcie_cap_slot_plug_cb(), +which sets dev->config byte 0x6e with bit PCI_EXP_SLTSTA_PDS to signal PCI +hotplug for the guest. After a while the guest will deal with this hotplug +and qemu will clear the above bit. + +Then, during migration, get_pci_config_device() will compare the +configs of both the freshly created device and the one that is being +received via migration, which will differ due to the PCI_EXP_SLTSTA_PDS bit +and cause the bug to reproduce. + +To avoid this fake incompatibility, there are tree fields in PCIDevice that +can help: + +- wmask: Used to implement R/W bytes, and +- w1cmask: Used to implement RW1C(Write 1 to Clear) bytes +- cmask: Used to enable config checks on load. + +According to PCI Express® Base Specification Revision 5.0 Version 1.0, +table 7-27 (Slot Status Register) bit 6, the "Presence Detect State" is +listed as RO (read-only), so it only makes sense to make use of the cmask +field. + +So, clear PCI_EXP_SLTSTA_PDS bit on cmask, so the fake incompatibility on +get_pci_config_device() does not abort the migration. + +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2215819 +Signed-off-by: Leonardo Bras +Message-Id: <20230706045546.593605-3-leobras@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Juan Quintela +(cherry picked from commit 625b370c45f4acd155ee625d61c0057d770a5b5e) +Signed-off-by: Leonardo Bras +--- + hw/pci/pcie.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c +index b8c24cf45f..8bc4a4ee57 100644 +--- a/hw/pci/pcie.c ++++ b/hw/pci/pcie.c +@@ -659,6 +659,10 @@ void pcie_cap_slot_init(PCIDevice *dev, PCIESlot *s) + pci_word_test_and_set_mask(dev->w1cmask + pos + PCI_EXP_SLTSTA, + PCI_EXP_HP_EV_SUPPORTED); + ++ /* Avoid migration abortion when this device hot-removed by guest */ ++ pci_word_test_and_clear_mask(dev->cmask + pos + PCI_EXP_SLTSTA, ++ PCI_EXP_SLTSTA_PDS); ++ + dev->exp.hpev_notified = false; + + qbus_set_hotplug_handler(BUS(pci_bridge_get_sec_bus(PCI_BRIDGE(dev))), +-- +2.39.3 + diff --git a/kvm-s390x-ap-Wire-up-the-device-request-notifier-interfa.patch b/kvm-s390x-ap-Wire-up-the-device-request-notifier-interfa.patch new file mode 100644 index 0000000..d0eb303 --- /dev/null +++ b/kvm-s390x-ap-Wire-up-the-device-request-notifier-interfa.patch @@ -0,0 +1,220 @@ +From 41987ce0dd79d8734088002cbd34f20704dd017a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Mon, 17 Jul 2023 17:36:07 +0200 +Subject: [PATCH 04/12] s390x/ap: Wire up the device request notifier interface +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Cédric Le Goater +RH-MergeRequest: 185: Backport s390x fixes from QEMU 8.1 +RH-Jira: RHEL-794 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Thomas Huth +RH-Commit: [1/1] ab6c912a1b8cdb584adacac16af79352fdfe7355 (clegoate/qemu-kvm-c9s) + +Jira: https://issues.redhat.com/browse/RHEL-794 + +commit 1360b2ad1f673d32a09de5826cd71ecd0510164a +Author: Tony Krowiak +Date: Fri Jun 2 10:11:25 2023 -0400 + + s390x/ap: Wire up the device request notifier interface + + Let's wire up the device request notifier interface to handle device unplug + requests for AP. + + Signed-off-by: Tony Krowiak + Link: https://lore.kernel.org/qemu-devel/20230530225544.280031-1-akrowiak@linux.ibm.com/ + Signed-off-by: Cédric Le Goater + +Backport note: + + - linux-headers/linux/vfio.h + updated to v6.5-rc1 level for VFIO_AP_REQ_IRQ_INDEX definition + +Signed-off-by: Cédric Le Goater +--- + hw/vfio/ap.c | 113 +++++++++++++++++++++++++++++++++++++ + linux-headers/linux/vfio.h | 9 +++ + 2 files changed, 122 insertions(+) + +diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c +index e0dd561e85..6e21d1da5a 100644 +--- a/hw/vfio/ap.c ++++ b/hw/vfio/ap.c +@@ -18,6 +18,8 @@ + #include "hw/vfio/vfio-common.h" + #include "hw/s390x/ap-device.h" + #include "qemu/error-report.h" ++#include "qemu/event_notifier.h" ++#include "qemu/main-loop.h" + #include "qemu/module.h" + #include "qemu/option.h" + #include "qemu/config-file.h" +@@ -33,6 +35,7 @@ + struct VFIOAPDevice { + APDevice apdev; + VFIODevice vdev; ++ EventNotifier req_notifier; + }; + + OBJECT_DECLARE_SIMPLE_TYPE(VFIOAPDevice, VFIO_AP_DEVICE) +@@ -84,10 +87,110 @@ static VFIOGroup *vfio_ap_get_group(VFIOAPDevice *vapdev, Error **errp) + return vfio_get_group(groupid, &address_space_memory, errp); + } + ++static void vfio_ap_req_notifier_handler(void *opaque) ++{ ++ VFIOAPDevice *vapdev = opaque; ++ Error *err = NULL; ++ ++ if (!event_notifier_test_and_clear(&vapdev->req_notifier)) { ++ return; ++ } ++ ++ qdev_unplug(DEVICE(vapdev), &err); ++ ++ if (err) { ++ warn_reportf_err(err, VFIO_MSG_PREFIX, vapdev->vdev.name); ++ } ++} ++ ++static void vfio_ap_register_irq_notifier(VFIOAPDevice *vapdev, ++ unsigned int irq, Error **errp) ++{ ++ int fd; ++ size_t argsz; ++ IOHandler *fd_read; ++ EventNotifier *notifier; ++ struct vfio_irq_info *irq_info; ++ VFIODevice *vdev = &vapdev->vdev; ++ ++ switch (irq) { ++ case VFIO_AP_REQ_IRQ_INDEX: ++ notifier = &vapdev->req_notifier; ++ fd_read = vfio_ap_req_notifier_handler; ++ break; ++ default: ++ error_setg(errp, "vfio: Unsupported device irq(%d)", irq); ++ return; ++ } ++ ++ if (vdev->num_irqs < irq + 1) { ++ error_setg(errp, "vfio: IRQ %u not available (number of irqs %u)", ++ irq, vdev->num_irqs); ++ return; ++ } ++ ++ argsz = sizeof(*irq_info); ++ irq_info = g_malloc0(argsz); ++ irq_info->index = irq; ++ irq_info->argsz = argsz; ++ ++ if (ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, ++ irq_info) < 0 || irq_info->count < 1) { ++ error_setg_errno(errp, errno, "vfio: Error getting irq info"); ++ goto out_free_info; ++ } ++ ++ if (event_notifier_init(notifier, 0)) { ++ error_setg_errno(errp, errno, ++ "vfio: Unable to init event notifier for irq (%d)", ++ irq); ++ goto out_free_info; ++ } ++ ++ fd = event_notifier_get_fd(notifier); ++ qemu_set_fd_handler(fd, fd_read, NULL, vapdev); ++ ++ if (vfio_set_irq_signaling(vdev, irq, 0, VFIO_IRQ_SET_ACTION_TRIGGER, fd, ++ errp)) { ++ qemu_set_fd_handler(fd, NULL, NULL, vapdev); ++ event_notifier_cleanup(notifier); ++ } ++ ++out_free_info: ++ g_free(irq_info); ++ ++} ++ ++static void vfio_ap_unregister_irq_notifier(VFIOAPDevice *vapdev, ++ unsigned int irq) ++{ ++ Error *err = NULL; ++ EventNotifier *notifier; ++ ++ switch (irq) { ++ case VFIO_AP_REQ_IRQ_INDEX: ++ notifier = &vapdev->req_notifier; ++ break; ++ default: ++ error_report("vfio: Unsupported device irq(%d)", irq); ++ return; ++ } ++ ++ if (vfio_set_irq_signaling(&vapdev->vdev, irq, 0, ++ VFIO_IRQ_SET_ACTION_TRIGGER, -1, &err)) { ++ warn_reportf_err(err, VFIO_MSG_PREFIX, vapdev->vdev.name); ++ } ++ ++ qemu_set_fd_handler(event_notifier_get_fd(notifier), ++ NULL, NULL, vapdev); ++ event_notifier_cleanup(notifier); ++} ++ + static void vfio_ap_realize(DeviceState *dev, Error **errp) + { + int ret; + char *mdevid; ++ Error *err = NULL; + VFIOGroup *vfio_group; + APDevice *apdev = AP_DEVICE(dev); + VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev); +@@ -116,6 +219,15 @@ static void vfio_ap_realize(DeviceState *dev, Error **errp) + goto out_get_dev_err; + } + ++ vfio_ap_register_irq_notifier(vapdev, VFIO_AP_REQ_IRQ_INDEX, &err); ++ if (err) { ++ /* ++ * Report this error, but do not make it a failing condition. ++ * Lack of this IRQ in the host does not prevent normal operation. ++ */ ++ error_report_err(err); ++ } ++ + return; + + out_get_dev_err: +@@ -129,6 +241,7 @@ static void vfio_ap_unrealize(DeviceState *dev) + VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev); + VFIOGroup *group = vapdev->vdev.group; + ++ vfio_ap_unregister_irq_notifier(vapdev, VFIO_AP_REQ_IRQ_INDEX); + vfio_ap_put_device(vapdev); + vfio_put_group(group); + } +diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h +index c59692ce0b..ce464957c8 100644 +--- a/linux-headers/linux/vfio.h ++++ b/linux-headers/linux/vfio.h +@@ -642,6 +642,15 @@ enum { + VFIO_CCW_NUM_IRQS + }; + ++/* ++ * The vfio-ap bus driver makes use of the following IRQ index mapping. ++ * Unimplemented IRQ types return a count of zero. ++ */ ++enum { ++ VFIO_AP_REQ_IRQ_INDEX, ++ VFIO_AP_NUM_IRQS ++}; ++ + /** + * VFIO_DEVICE_GET_PCI_HOT_RESET_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 12, + * struct vfio_pci_hot_reset_info) +-- +2.39.3 + diff --git a/kvm-scsi-cleanup-scsi_clear_unit_attention.patch b/kvm-scsi-cleanup-scsi_clear_unit_attention.patch new file mode 100644 index 0000000..11dda3a --- /dev/null +++ b/kvm-scsi-cleanup-scsi_clear_unit_attention.patch @@ -0,0 +1,81 @@ +From 5dd7d26c034c26b2d4d9b91b8d1a7b605e19730f Mon Sep 17 00:00:00 2001 +From: Stefano Garzarella +Date: Wed, 12 Jul 2023 15:43:51 +0200 +Subject: [PATCH 02/12] scsi: cleanup scsi_clear_unit_attention() + +RH-Author: Stefano Garzarella +RH-MergeRequest: 184: scsi: fix issue with Linux guest and unit attention +RH-Bugzilla: 2176702 +RH-Acked-by: Thomas Huth +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Commit: [2/3] b3a06a91644e44fae3d76d0fbe72448652db517a (sgarzarella/qemu-kvm-c-9-s) + +The previous commit moved the unit attention clearing when we create +the request. So now we can clean scsi_clear_unit_attention() to handle +only the case of the REPORT LUNS command: this is the only case in +which a UNIT ATTENTION is cleared without having been reported. + +Suggested-by: Paolo Bonzini +Signed-off-by: Stefano Garzarella +Message-ID: <20230712134352.118655-3-sgarzare@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit ba947dab98e7cd4337c70975bd255701a2a6aad8) +Signed-off-by: Stefano Garzarella +--- + hw/scsi/scsi-bus.c | 28 ++++++---------------------- + 1 file changed, 6 insertions(+), 22 deletions(-) + +diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c +index 5d22313b9d..cecd26479e 100644 +--- a/hw/scsi/scsi-bus.c ++++ b/hw/scsi/scsi-bus.c +@@ -828,26 +828,12 @@ static void scsi_clear_unit_attention(SCSIRequest *req) + return; + } + +- if (req->dev->unit_attention.key != UNIT_ATTENTION && +- req->bus->unit_attention.key != UNIT_ATTENTION) { +- return; +- } +- +- /* +- * If an INQUIRY command enters the enabled command state, +- * the device server shall [not] clear any unit attention condition; +- * See also MMC-6, paragraphs 6.5 and 6.6.2. +- */ +- if (req->cmd.buf[0] == INQUIRY || +- req->cmd.buf[0] == GET_CONFIGURATION || +- req->cmd.buf[0] == GET_EVENT_STATUS_NOTIFICATION) { +- return; +- } +- + if (req->dev->unit_attention.key == UNIT_ATTENTION) { + ua = &req->dev->unit_attention; +- } else { ++ } else if (req->bus->unit_attention.key == UNIT_ATTENTION) { + ua = &req->bus->unit_attention; ++ } else { ++ return; + } + + /* +@@ -856,12 +842,10 @@ static void scsi_clear_unit_attention(SCSIRequest *req) + * with an additional sense code of REPORTED LUNS DATA HAS CHANGED. + */ + if (req->cmd.buf[0] == REPORT_LUNS && +- !(ua->asc == SENSE_CODE(REPORTED_LUNS_CHANGED).asc && +- ua->ascq == SENSE_CODE(REPORTED_LUNS_CHANGED).ascq)) { +- return; ++ ua->asc == SENSE_CODE(REPORTED_LUNS_CHANGED).asc && ++ ua->ascq == SENSE_CODE(REPORTED_LUNS_CHANGED).ascq) { ++ *ua = SENSE_CODE(NO_SENSE); + } +- +- *ua = SENSE_CODE(NO_SENSE); + } + + int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len) +-- +2.39.3 + diff --git a/kvm-scsi-clear-unit-attention-only-for-REPORT-LUNS-comma.patch b/kvm-scsi-clear-unit-attention-only-for-REPORT-LUNS-comma.patch new file mode 100644 index 0000000..cb3b24e --- /dev/null +++ b/kvm-scsi-clear-unit-attention-only-for-REPORT-LUNS-comma.patch @@ -0,0 +1,110 @@ +From 0a784c45a7b7ee32c36bf86eebb24c8431a89f49 Mon Sep 17 00:00:00 2001 +From: Stefano Garzarella +Date: Wed, 12 Jul 2023 15:43:52 +0200 +Subject: [PATCH 03/12] scsi: clear unit attention only for REPORT LUNS + commands + +RH-Author: Stefano Garzarella +RH-MergeRequest: 184: scsi: fix issue with Linux guest and unit attention +RH-Bugzilla: 2176702 +RH-Acked-by: Thomas Huth +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Commit: [3/3] 01d5e112ef9ae204d96ceb01b4a453fdb4e8b669 (sgarzarella/qemu-kvm-c-9-s) + +scsi_clear_unit_attention() now only handles REPORTED LUNS DATA HAS +CHANGED. + +This only happens when we handle REPORT LUNS commands, so let's rename +the function in scsi_clear_reported_luns_changed() and call it only in +scsi_target_emulate_report_luns(). + +Suggested-by: Paolo Bonzini +Signed-off-by: Stefano Garzarella +Message-ID: <20230712134352.118655-4-sgarzare@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 2eb5599e8a73e70a9e86a97120818ff95a43a23a) +Signed-off-by: Stefano Garzarella +--- + hw/scsi/scsi-bus.c | 34 +++++++++++----------------------- + 1 file changed, 11 insertions(+), 23 deletions(-) + +diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c +index cecd26479e..9542410800 100644 +--- a/hw/scsi/scsi-bus.c ++++ b/hw/scsi/scsi-bus.c +@@ -22,6 +22,7 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev); + static void scsi_req_dequeue(SCSIRequest *req); + static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len); + static void scsi_target_free_buf(SCSIRequest *req); ++static void scsi_clear_reported_luns_changed(SCSIRequest *req); + + static int next_scsi_bus; + +@@ -518,6 +519,14 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r) + + /* store the LUN list length */ + stl_be_p(&r->buf[0], len - 8); ++ ++ /* ++ * If a REPORT LUNS command enters the enabled command state, [...] ++ * the device server shall clear any pending unit attention condition ++ * with an additional sense code of REPORTED LUNS DATA HAS CHANGED. ++ */ ++ scsi_clear_reported_luns_changed(&r->req); ++ + return true; + } + +@@ -816,18 +825,10 @@ uint8_t *scsi_req_get_buf(SCSIRequest *req) + return req->ops->get_buf(req); + } + +-static void scsi_clear_unit_attention(SCSIRequest *req) ++static void scsi_clear_reported_luns_changed(SCSIRequest *req) + { + SCSISense *ua; + +- /* +- * scsi_fetch_unit_attention_sense() already cleaned the unit attention +- * in this case. +- */ +- if (req->ops == &reqops_unit_attention) { +- return; +- } +- + if (req->dev->unit_attention.key == UNIT_ATTENTION) { + ua = &req->dev->unit_attention; + } else if (req->bus->unit_attention.key == UNIT_ATTENTION) { +@@ -836,13 +837,7 @@ static void scsi_clear_unit_attention(SCSIRequest *req) + return; + } + +- /* +- * If a REPORT LUNS command enters the enabled command state, [...] +- * the device server shall clear any pending unit attention condition +- * with an additional sense code of REPORTED LUNS DATA HAS CHANGED. +- */ +- if (req->cmd.buf[0] == REPORT_LUNS && +- ua->asc == SENSE_CODE(REPORTED_LUNS_CHANGED).asc && ++ if (ua->asc == SENSE_CODE(REPORTED_LUNS_CHANGED).asc && + ua->ascq == SENSE_CODE(REPORTED_LUNS_CHANGED).ascq) { + *ua = SENSE_CODE(NO_SENSE); + } +@@ -1528,13 +1523,6 @@ void scsi_req_complete(SCSIRequest *req, int status) + req->dev->sense_is_ua = false; + } + +- /* +- * Unit attention state is now stored in the device's sense buffer +- * if the HBA didn't do autosense. Clear the pending unit attention +- * flags. +- */ +- scsi_clear_unit_attention(req); +- + scsi_req_ref(req); + scsi_req_dequeue(req); + req->bus->info->complete(req, req->residual); +-- +2.39.3 + diff --git a/kvm-scsi-fetch-unit-attention-when-creating-the-request.patch b/kvm-scsi-fetch-unit-attention-when-creating-the-request.patch new file mode 100644 index 0000000..a41ae82 --- /dev/null +++ b/kvm-scsi-fetch-unit-attention-when-creating-the-request.patch @@ -0,0 +1,132 @@ +From 562ea3a2d602cf41c548f3ddf52c43c04fded347 Mon Sep 17 00:00:00 2001 +From: Stefano Garzarella +Date: Wed, 12 Jul 2023 15:43:50 +0200 +Subject: [PATCH 01/12] scsi: fetch unit attention when creating the request + +RH-Author: Stefano Garzarella +RH-MergeRequest: 184: scsi: fix issue with Linux guest and unit attention +RH-Bugzilla: 2176702 +RH-Acked-by: Thomas Huth +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Commit: [1/3] 04563caac45d0110ea65eda8e55472556cd317c0 (sgarzarella/qemu-kvm-c-9-s) + +Commit 1880ad4f4e ("virtio-scsi: Batched prepare for cmd reqs") split +calls to scsi_req_new() and scsi_req_enqueue() in the virtio-scsi device. +No ill effects were observed until commit 8cc5583abe ("virtio-scsi: Send +"REPORTED LUNS CHANGED" sense data upon disk hotplug events") added a +unit attention that was easy to trigger with device hotplug and +hot-unplug. + +Because the two calls were separated, all requests in the batch were +prepared calling scsi_req_new() to report a sense. The first one +submitted would report the right sense and reset it to NO_SENSE, while +the others reported CHECK_CONDITION with no sense data. This caused +SCSI errors in Linux. + +To solve this issue, let's fetch the unit attention as early as possible +when we prepare the request, so that only the first request in the batch +will use the unit attention SCSIReqOps and the others will not report +CHECK CONDITION. + +Fixes: 1880ad4f4e ("virtio-scsi: Batched prepare for cmd reqs") +Fixes: 8cc5583abe ("virtio-scsi: Send "REPORTED LUNS CHANGED" sense data upon disk hotplug events") +Reported-by: Thomas Huth +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2176702 +Co-developed-by: Paolo Bonzini +Signed-off-by: Stefano Garzarella +Message-ID: <20230712134352.118655-2-sgarzare@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 9472083e642bfb9bc836b38662baddd9bc964ebc) +Signed-off-by: Stefano Garzarella +--- + hw/scsi/scsi-bus.c | 36 +++++++++++++++++++++++++++++++++--- + include/hw/scsi/scsi.h | 1 + + 2 files changed, 34 insertions(+), 3 deletions(-) + +diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c +index 3c20b47ad0..5d22313b9d 100644 +--- a/hw/scsi/scsi-bus.c ++++ b/hw/scsi/scsi-bus.c +@@ -413,19 +413,35 @@ static const struct SCSIReqOps reqops_invalid_opcode = { + + /* SCSIReqOps implementation for unit attention conditions. */ + +-static int32_t scsi_unit_attention(SCSIRequest *req, uint8_t *buf) ++static void scsi_fetch_unit_attention_sense(SCSIRequest *req) + { ++ SCSISense *ua = NULL; ++ + if (req->dev->unit_attention.key == UNIT_ATTENTION) { +- scsi_req_build_sense(req, req->dev->unit_attention); ++ ua = &req->dev->unit_attention; + } else if (req->bus->unit_attention.key == UNIT_ATTENTION) { +- scsi_req_build_sense(req, req->bus->unit_attention); ++ ua = &req->bus->unit_attention; + } ++ ++ /* ++ * Fetch the unit attention sense immediately so that another ++ * scsi_req_new does not use reqops_unit_attention. ++ */ ++ if (ua) { ++ scsi_req_build_sense(req, *ua); ++ *ua = SENSE_CODE(NO_SENSE); ++ } ++} ++ ++static int32_t scsi_unit_attention(SCSIRequest *req, uint8_t *buf) ++{ + scsi_req_complete(req, CHECK_CONDITION); + return 0; + } + + static const struct SCSIReqOps reqops_unit_attention = { + .size = sizeof(SCSIRequest), ++ .init_req = scsi_fetch_unit_attention_sense, + .send_command = scsi_unit_attention + }; + +@@ -699,6 +715,11 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d, + object_ref(OBJECT(d)); + object_ref(OBJECT(qbus->parent)); + notifier_list_init(&req->cancel_notifiers); ++ ++ if (reqops->init_req) { ++ reqops->init_req(req); ++ } ++ + trace_scsi_req_alloc(req->dev->id, req->lun, req->tag); + return req; + } +@@ -798,6 +819,15 @@ uint8_t *scsi_req_get_buf(SCSIRequest *req) + static void scsi_clear_unit_attention(SCSIRequest *req) + { + SCSISense *ua; ++ ++ /* ++ * scsi_fetch_unit_attention_sense() already cleaned the unit attention ++ * in this case. ++ */ ++ if (req->ops == &reqops_unit_attention) { ++ return; ++ } ++ + if (req->dev->unit_attention.key != UNIT_ATTENTION && + req->bus->unit_attention.key != UNIT_ATTENTION) { + return; +diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h +index 6f23a7a73e..1787ddd01e 100644 +--- a/include/hw/scsi/scsi.h ++++ b/include/hw/scsi/scsi.h +@@ -108,6 +108,7 @@ int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num); + /* scsi-bus.c */ + struct SCSIReqOps { + size_t size; ++ void (*init_req)(SCSIRequest *req); + void (*free_req)(SCSIRequest *req); + int32_t (*send_command)(SCSIRequest *req, uint8_t *buf); + void (*read_data)(SCSIRequest *req); +-- +2.39.3 + diff --git a/qemu.spec b/qemu.spec index ed91c06..a014189 100644 --- a/qemu.spec +++ b/qemu.spec @@ -149,7 +149,7 @@ Obsoletes: %{name}-block-ssh <= %{epoch}:%{version} \ Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 8.0.0 -Release: 8%{?rcrel}%{?dist}%{?cc_suffix} +Release: 9%{?rcrel}%{?dist}%{?cc_suffix} # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped # Epoch 15 used for RHEL 8 # Epoch 17 used for RHEL 9 (due to release versioning offset in RHEL 8.5) @@ -446,6 +446,28 @@ Patch144: kvm-pc-bios-s390-ccw-Don-t-use-__bss_start-with-the-larl.patch Patch145: kvm-ui-Fix-pixel-colour-channel-order-for-PNG-screenshot.patch # For bz#2213317 - Enable libblkio-based block drivers in QEMU Patch146: kvm-block-blkio-fix-module_block.py-parsing.patch +# For bz#2176702 - [RHEL9][virtio-scsi] scsi-hd cannot hot-plug successfully after hot-plug it repeatly +Patch147: kvm-scsi-fetch-unit-attention-when-creating-the-request.patch +# For bz#2176702 - [RHEL9][virtio-scsi] scsi-hd cannot hot-plug successfully after hot-plug it repeatly +Patch148: kvm-scsi-cleanup-scsi_clear_unit_attention.patch +# For bz#2176702 - [RHEL9][virtio-scsi] scsi-hd cannot hot-plug successfully after hot-plug it repeatly +Patch149: kvm-scsi-clear-unit-attention-only-for-REPORT-LUNS-comma.patch +# For RHEL-794 - Backport s390x fixes from QEMU 8.1 +Patch150: kvm-s390x-ap-Wire-up-the-device-request-notifier-interfa.patch +# For bz#2196295 - Multifd flushes its channels 10 times per second +Patch151: kvm-multifd-Create-property-multifd-flush-after-each-sec.patch +# For bz#2196295 - Multifd flushes its channels 10 times per second +Patch152: kvm-multifd-Protect-multifd_send_sync_main-calls.patch +# For bz#2196295 - Multifd flushes its channels 10 times per second +Patch153: kvm-multifd-Only-flush-once-each-full-round-of-memory.patch +# For RHEL-582 - [passt][rhel 9.3] qemu core dump occurs when guest is shutdown after hotunplug/hotplug a passt interface +Patch154: kvm-net-socket-prepare-to-cleanup-net_init_socket.patch +# For RHEL-582 - [passt][rhel 9.3] qemu core dump occurs when guest is shutdown after hotunplug/hotplug a passt interface +Patch155: kvm-net-socket-move-fd-type-checking-to-its-own-function.patch +# For RHEL-582 - [passt][rhel 9.3] qemu core dump occurs when guest is shutdown after hotunplug/hotplug a passt interface +Patch156: kvm-net-socket-remove-net_init_socket.patch +# For bz#2215819 - Migration test failed while guest with PCIe devices +Patch157: kvm-pcie-Add-hotplug-detect-state-register-to-cmask.patch # ELN specific changes Patch1001: 1001-keymaps-use-ara-X11-keyboard-map-instead-of-ar.patch @@ -760,6 +782,19 @@ Obsoletes: %{name}-hw-usbredir <= %{epoch}:%{version} This package provides usbredir support. %endif +%package ui-dbus +Summary: QEMU D-Bus UI driver +Requires: %{name}-common%{?_isa} = %{epoch}:%{version}-%{release} +%description ui-dbus +This package provides the additional D-Bus UI for QEMU. + +%package audio-dbus +Summary: QEMU D-Bus audio driver +Requires: %{name}-common%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ui-dbus = %{epoch}:%{version}-%{release} +%description audio-dbus +This package provides the additional D-Bus audio driver for QEMU. + %prep %setup -q -n qemu-%{version}%{?rcstr} %autopatch -p1 @@ -962,11 +997,13 @@ run_configure \ --enable-capstone \ --enable-coroutine-pool \ --enable-curl \ + --enable-dbus-display \ --enable-debug-info \ --enable-docs \ %if %{have_fdt} --enable-fdt=system \ %endif + --enable-gio \ --enable-gnutls \ --enable-guest-agent \ --enable-iconv \ @@ -1485,10 +1522,42 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %{_libdir}/%{name}/hw-usb-redirect.so %endif +%files audio-dbus +%{_libdir}/%{name}/audio-dbus.so + +%files ui-dbus +%{_libdir}/%{name}/ui-dbus.so + # endif !tools_only %endif %changelog +* Mon Jul 24 2023 Miroslav Rezanina - 8.0.0-9 +- kvm-scsi-fetch-unit-attention-when-creating-the-request.patch [bz#2176702] +- kvm-scsi-cleanup-scsi_clear_unit_attention.patch [bz#2176702] +- kvm-scsi-clear-unit-attention-only-for-REPORT-LUNS-comma.patch [bz#2176702] +- kvm-s390x-ap-Wire-up-the-device-request-notifier-interfa.patch [RHEL-794] +- kvm-multifd-Create-property-multifd-flush-after-each-sec.patch [bz#2196295] +- kvm-multifd-Protect-multifd_send_sync_main-calls.patch [bz#2196295] +- kvm-multifd-Only-flush-once-each-full-round-of-memory.patch [bz#2196295] +- kvm-net-socket-prepare-to-cleanup-net_init_socket.patch [RHEL-582] +- kvm-net-socket-move-fd-type-checking-to-its-own-function.patch [RHEL-582] +- kvm-net-socket-remove-net_init_socket.patch [RHEL-582] +- kvm-pcie-Add-hotplug-detect-state-register-to-cmask.patch [bz#2215819] +- kvm-spec-Build-DBUS-display.patch [bz#2207940] +- Resolves: bz#2176702 + ([RHEL9][virtio-scsi] scsi-hd cannot hot-plug successfully after hot-plug it repeatly) +- Resolves: RHEL-794 + (Backport s390x fixes from QEMU 8.1) +- Resolves: bz#2196295 + (Multifd flushes its channels 10 times per second) +- Resolves: RHEL-582 + ([passt][rhel 9.3] qemu core dump occurs when guest is shutdown after hotunplug/hotplug a passt interface) +- Resolves: bz#2215819 + (Migration test failed while guest with PCIe devices) +- Resolves: bz#2207940 + ([RFE] Enable qemu-ui-dbus subpackage) + * Mon Jul 17 2023 Miroslav Rezanina - 8.0.0-8 - kvm-virtio-iommu-Fix-64kB-host-page-size-VFIO-device-ass.patch [bz#2211609 bz#2211634] - kvm-virtio-iommu-Rework-the-traces-in-virtio_iommu_set_p.patch [bz#2211609 bz#2211634]