diff --git a/kvm-io-ensure-UNIX-client-doesn-t-unlink-server-socket.patch b/kvm-io-ensure-UNIX-client-doesn-t-unlink-server-socket.patch new file mode 100644 index 0000000..860e1a4 --- /dev/null +++ b/kvm-io-ensure-UNIX-client-doesn-t-unlink-server-socket.patch @@ -0,0 +1,294 @@ +From dea7d39cce3b1da16de0bfb47a028f770547098a Mon Sep 17 00:00:00 2001 +From: "Daniel P. Berrange" +Date: Tue, 29 Jan 2019 13:58:57 +0000 +Subject: [PATCH 1/3] io: ensure UNIX client doesn't unlink server socket +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrange +Message-id: <20190129135857.10581-2-berrange@redhat.com> +Patchwork-id: 84141 +O-Subject: [RHEL-8.0/AV qemu-kvm PATCH 1/1] io: ensure UNIX client doesn't unlink server socket +Bugzilla: 1665896 +RH-Acked-by: John Snow +RH-Acked-by: Thomas Huth +RH-Acked-by: Philippe Mathieu-Daudé + +The qio_channel_socket_close method for was mistakenly unlinking the +UNIX server socket, even if the channel was a client connection. This +was not noticed with chardevs, since they never call close, but with the +VNC server, this caused the VNC server socket to be deleted after the +first client quit. + +The qio_channel_socket_close method also needlessly reimplemented the +logic that already exists in socket_listen_cleanup(). Just call that +method directly, for listen sockets only. + +This fixes a regression introduced in QEMU 3.0.0 with + + commit d66f78e1eaa832f73c771d9df1b606fe75d52a50 + Author: Pavel Balaev + Date: Mon May 21 19:17:35 2018 +0300 + + Delete AF_UNIX socket after close + +Fixes launchpad #1795100 + +Reviewed-by: Eric Blake +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 73564c407caedf992a1c688b5fea776a8b56ba2a) +Signed-off-by: Danilo C. L. de Paula +--- + io/channel-socket.c | 19 ++-------- + tests/test-io-channel-socket.c | 86 +++++++++++++++++++++++++++++++++++++----- + 2 files changed, 80 insertions(+), 25 deletions(-) + +diff --git a/io/channel-socket.c b/io/channel-socket.c +index b50e63a..bc5f80e 100644 +--- a/io/channel-socket.c ++++ b/io/channel-socket.c +@@ -688,10 +688,13 @@ qio_channel_socket_close(QIOChannel *ioc, + int rc = 0; + + if (sioc->fd != -1) { +- SocketAddress *addr = socket_local_address(sioc->fd, errp); + #ifdef WIN32 + WSAEventSelect(sioc->fd, NULL, 0); + #endif ++ if (qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_LISTEN)) { ++ socket_listen_cleanup(sioc->fd, errp); ++ } ++ + if (closesocket(sioc->fd) < 0) { + sioc->fd = -1; + error_setg_errno(errp, errno, +@@ -699,20 +702,6 @@ qio_channel_socket_close(QIOChannel *ioc, + return -1; + } + sioc->fd = -1; +- +- if (addr && addr->type == SOCKET_ADDRESS_TYPE_UNIX +- && addr->u.q_unix.path) { +- if (unlink(addr->u.q_unix.path) < 0 && errno != ENOENT) { +- error_setg_errno(errp, errno, +- "Failed to unlink socket %s", +- addr->u.q_unix.path); +- rc = -1; +- } +- } +- +- if (addr) { +- qapi_free_SocketAddress(addr); +- } + } + return rc; + } +diff --git a/tests/test-io-channel-socket.c b/tests/test-io-channel-socket.c +index 0597213..c253ae3 100644 +--- a/tests/test-io-channel-socket.c ++++ b/tests/test-io-channel-socket.c +@@ -49,6 +49,7 @@ static void test_io_channel_set_socket_bufs(QIOChannel *src, + + static void test_io_channel_setup_sync(SocketAddress *listen_addr, + SocketAddress *connect_addr, ++ QIOChannel **srv, + QIOChannel **src, + QIOChannel **dst) + { +@@ -78,7 +79,7 @@ static void test_io_channel_setup_sync(SocketAddress *listen_addr, + + test_io_channel_set_socket_bufs(*src, *dst); + +- object_unref(OBJECT(lioc)); ++ *srv = QIO_CHANNEL(lioc); + } + + +@@ -99,6 +100,7 @@ static void test_io_channel_complete(QIOTask *task, + + static void test_io_channel_setup_async(SocketAddress *listen_addr, + SocketAddress *connect_addr, ++ QIOChannel **srv, + QIOChannel **src, + QIOChannel **dst) + { +@@ -146,21 +148,34 @@ static void test_io_channel_setup_async(SocketAddress *listen_addr, + qio_channel_set_delay(*src, false); + test_io_channel_set_socket_bufs(*src, *dst); + +- object_unref(OBJECT(lioc)); ++ *srv = QIO_CHANNEL(lioc); + + g_main_loop_unref(data.loop); + } + + ++static void test_io_channel_socket_path_exists(SocketAddress *addr, ++ bool expectExists) ++{ ++ if (addr->type != SOCKET_ADDRESS_TYPE_UNIX) { ++ return; ++ } ++ ++ g_assert(g_file_test(addr->u.q_unix.path, ++ G_FILE_TEST_EXISTS) == expectExists); ++} ++ ++ + static void test_io_channel(bool async, + SocketAddress *listen_addr, + SocketAddress *connect_addr, + bool passFD) + { +- QIOChannel *src, *dst; ++ QIOChannel *src, *dst, *srv; + QIOChannelTest *test; + if (async) { +- test_io_channel_setup_async(listen_addr, connect_addr, &src, &dst); ++ test_io_channel_setup_async(listen_addr, connect_addr, ++ &srv, &src, &dst); + + g_assert(!passFD || + qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS)); +@@ -169,14 +184,25 @@ static void test_io_channel(bool async, + g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN)); + g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN)); + ++ test_io_channel_socket_path_exists(listen_addr, true); ++ + test = qio_channel_test_new(); + qio_channel_test_run_threads(test, true, src, dst); + qio_channel_test_validate(test); + ++ test_io_channel_socket_path_exists(listen_addr, true); ++ ++ /* unref without close, to ensure finalize() cleans up */ ++ + object_unref(OBJECT(src)); + object_unref(OBJECT(dst)); ++ test_io_channel_socket_path_exists(listen_addr, true); + +- test_io_channel_setup_async(listen_addr, connect_addr, &src, &dst); ++ object_unref(OBJECT(srv)); ++ test_io_channel_socket_path_exists(listen_addr, false); ++ ++ test_io_channel_setup_async(listen_addr, connect_addr, ++ &srv, &src, &dst); + + g_assert(!passFD || + qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS)); +@@ -189,10 +215,24 @@ static void test_io_channel(bool async, + qio_channel_test_run_threads(test, false, src, dst); + qio_channel_test_validate(test); + ++ /* close before unref, to ensure finalize copes with already closed */ ++ ++ qio_channel_close(src, &error_abort); ++ qio_channel_close(dst, &error_abort); ++ test_io_channel_socket_path_exists(listen_addr, true); ++ + object_unref(OBJECT(src)); + object_unref(OBJECT(dst)); ++ test_io_channel_socket_path_exists(listen_addr, true); ++ ++ qio_channel_close(srv, &error_abort); ++ test_io_channel_socket_path_exists(listen_addr, false); ++ ++ object_unref(OBJECT(srv)); ++ test_io_channel_socket_path_exists(listen_addr, false); + } else { +- test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst); ++ test_io_channel_setup_sync(listen_addr, connect_addr, ++ &srv, &src, &dst); + + g_assert(!passFD || + qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS)); +@@ -201,14 +241,25 @@ static void test_io_channel(bool async, + g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN)); + g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN)); + ++ test_io_channel_socket_path_exists(listen_addr, true); ++ + test = qio_channel_test_new(); + qio_channel_test_run_threads(test, true, src, dst); + qio_channel_test_validate(test); + ++ test_io_channel_socket_path_exists(listen_addr, true); ++ ++ /* unref without close, to ensure finalize() cleans up */ ++ + object_unref(OBJECT(src)); + object_unref(OBJECT(dst)); ++ test_io_channel_socket_path_exists(listen_addr, true); ++ ++ object_unref(OBJECT(srv)); ++ test_io_channel_socket_path_exists(listen_addr, false); + +- test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst); ++ test_io_channel_setup_sync(listen_addr, connect_addr, ++ &srv, &src, &dst); + + g_assert(!passFD || + qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS)); +@@ -221,8 +272,23 @@ static void test_io_channel(bool async, + qio_channel_test_run_threads(test, false, src, dst); + qio_channel_test_validate(test); + ++ test_io_channel_socket_path_exists(listen_addr, true); ++ ++ /* close before unref, to ensure finalize copes with already closed */ ++ ++ qio_channel_close(src, &error_abort); ++ qio_channel_close(dst, &error_abort); ++ test_io_channel_socket_path_exists(listen_addr, true); ++ + object_unref(OBJECT(src)); + object_unref(OBJECT(dst)); ++ test_io_channel_socket_path_exists(listen_addr, true); ++ ++ qio_channel_close(srv, &error_abort); ++ test_io_channel_socket_path_exists(listen_addr, false); ++ ++ object_unref(OBJECT(srv)); ++ test_io_channel_socket_path_exists(listen_addr, false); + } + } + +@@ -316,7 +382,6 @@ static void test_io_channel_unix(bool async) + + qapi_free_SocketAddress(listen_addr); + qapi_free_SocketAddress(connect_addr); +- g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS) == FALSE); + } + + +@@ -335,7 +400,7 @@ static void test_io_channel_unix_fd_pass(void) + { + SocketAddress *listen_addr = g_new0(SocketAddress, 1); + SocketAddress *connect_addr = g_new0(SocketAddress, 1); +- QIOChannel *src, *dst; ++ QIOChannel *src, *dst, *srv; + int testfd; + int fdsend[3]; + int *fdrecv = NULL; +@@ -359,7 +424,7 @@ static void test_io_channel_unix_fd_pass(void) + connect_addr->type = SOCKET_ADDRESS_TYPE_UNIX; + connect_addr->u.q_unix.path = g_strdup(TEST_SOCKET); + +- test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst); ++ test_io_channel_setup_sync(listen_addr, connect_addr, &srv, &src, &dst); + + memcpy(bufsend, "Hello World", G_N_ELEMENTS(bufsend)); + +@@ -412,6 +477,7 @@ static void test_io_channel_unix_fd_pass(void) + + object_unref(OBJECT(src)); + object_unref(OBJECT(dst)); ++ object_unref(OBJECT(srv)); + qapi_free_SocketAddress(listen_addr); + qapi_free_SocketAddress(connect_addr); + unlink(TEST_SOCKET); +-- +1.8.3.1 + diff --git a/kvm-scsi-disk-Add-device_id-property.patch b/kvm-scsi-disk-Add-device_id-property.patch new file mode 100644 index 0000000..96d7d9b --- /dev/null +++ b/kvm-scsi-disk-Add-device_id-property.patch @@ -0,0 +1,98 @@ +From c9f6e5639cc9d7b1d336b55ccacb6673933a3864 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Feb 2019 15:58:29 +0000 +Subject: [PATCH 3/3] scsi-disk: Add device_id property + +RH-Author: Kevin Wolf +Message-id: <20190206155829.14641-3-kwolf@redhat.com> +Patchwork-id: 84254 +O-Subject: [RHEL-7.7/8.0-AV qemu-kvm-rhev PATCH 2/2] scsi-disk: Add device_id property +Bugzilla: 1668248 +RH-Acked-by: Max Reitz +RH-Acked-by: Thomas Huth +RH-Acked-by: Paolo Bonzini + +The new device_id property specifies which value to use for the vendor +specific designator in the Device Identification VPD page. + +In particular, this is necessary for libvirt to maintain guest ABI +compatibility when no serial number is given and a VM is switched from +-drive (where the BlockBackend name is used) to -blockdev (where the +vendor specific designator is left out by default). + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 7471a649fc3a391dd497297013fb2525ca9821ba) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + hw/scsi/scsi-disk.c | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c +index 93eef40..e74e1e7 100644 +--- a/hw/scsi/scsi-disk.c ++++ b/hw/scsi/scsi-disk.c +@@ -104,6 +104,7 @@ typedef struct SCSIDiskState + char *serial; + char *vendor; + char *product; ++ char *device_id; + bool tray_open; + bool tray_locked; + /* +@@ -642,13 +643,8 @@ static int scsi_disk_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf) + + case 0x83: /* Device identification page, mandatory */ + { +- const char *str = s->serial ?: blk_name(s->qdev.conf.blk); +- int max_len = s->serial ? 20 : 255 - 8; +- int id_len = strlen(str); ++ int id_len = s->device_id ? MIN(strlen(s->device_id), 255 - 8) : 0; + +- if (id_len > max_len) { +- id_len = max_len; +- } + DPRINTF("Inquiry EVPD[Device identification] " + "buffer size %zd\n", req->cmd.xfer); + +@@ -657,7 +653,7 @@ static int scsi_disk_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf) + outbuf[buflen++] = 0; /* not officially assigned */ + outbuf[buflen++] = 0; /* reserved */ + outbuf[buflen++] = id_len; /* length of data following */ +- memcpy(outbuf + buflen, str, id_len); ++ memcpy(outbuf + buflen, s->device_id, id_len); + buflen += id_len; + } + +@@ -2363,6 +2359,16 @@ static void scsi_realize(SCSIDevice *dev, Error **errp) + if (!s->vendor) { + s->vendor = g_strdup("QEMU"); + } ++ if (!s->device_id) { ++ if (s->serial) { ++ s->device_id = g_strdup_printf("%.20s", s->serial); ++ } else { ++ const char *str = blk_name(s->qdev.conf.blk); ++ if (str && *str) { ++ s->device_id = g_strdup(str); ++ } ++ } ++ } + + if (blk_is_sg(s->qdev.conf.blk)) { + error_setg(errp, "unwanted /dev/sg*"); +@@ -2904,7 +2910,9 @@ static const TypeInfo scsi_disk_base_info = { + DEFINE_PROP_STRING("ver", SCSIDiskState, version), \ + DEFINE_PROP_STRING("serial", SCSIDiskState, serial), \ + DEFINE_PROP_STRING("vendor", SCSIDiskState, vendor), \ +- DEFINE_PROP_STRING("product", SCSIDiskState, product) ++ DEFINE_PROP_STRING("product", SCSIDiskState, product), \ ++ DEFINE_PROP_STRING("device_id", SCSIDiskState, device_id) ++ + + static Property scsi_hd_properties[] = { + DEFINE_SCSI_DISK_PROPERTIES(), +-- +1.8.3.1 + diff --git a/kvm-scsi-disk-Don-t-use-empty-string-as-device-id.patch b/kvm-scsi-disk-Don-t-use-empty-string-as-device-id.patch new file mode 100644 index 0000000..c08ea92 --- /dev/null +++ b/kvm-scsi-disk-Don-t-use-empty-string-as-device-id.patch @@ -0,0 +1,71 @@ +From 18d600a76319abe59dc4b5e371e5807c089f9159 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Feb 2019 15:58:28 +0000 +Subject: [PATCH 2/3] scsi-disk: Don't use empty string as device id +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Kevin Wolf +Message-id: <20190206155829.14641-2-kwolf@redhat.com> +Patchwork-id: 84253 +O-Subject: [RHEL-7.7/8.0-AV qemu-kvm-rhev PATCH 1/2] scsi-disk: Don't use empty string as device id +Bugzilla: 1668248 +RH-Acked-by: Max Reitz +RH-Acked-by: Thomas Huth +RH-Acked-by: Paolo Bonzini + +scsi-disk includes in the Device Identification VPD page, depending on +configuration amongst others, a vendor specific designator that consists +either of the serial number if given or the BlockBackend name (which is +a host detail that better shouldn't have been leaked to the guest, but +now we have to maintain it for compatibility). + +With anonymous BlockBackends, i.e. scsi-disk devices constructed with +drive=, and no serial number explicitly specified, this ends +up as an empty string. If this happens to more than one disk, we have +accidentally signalled to the OS that this is a multipath setup, which +is obviously not what was intended. + +Instead of using an empty string for the vendor specific designator, +simply leave out that designator, which makes Linux detect such setups +as separate disks again. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Reviewed-by: Philippe Mathieu-Daudé +(cherry picked from commit a8f58afcdb86e266e06c9dc41a71605e570244c3) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + hw/scsi/scsi-disk.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c +index 0e9027c..93eef40 100644 +--- a/hw/scsi/scsi-disk.c ++++ b/hw/scsi/scsi-disk.c +@@ -652,12 +652,14 @@ static int scsi_disk_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf) + DPRINTF("Inquiry EVPD[Device identification] " + "buffer size %zd\n", req->cmd.xfer); + +- outbuf[buflen++] = 0x2; /* ASCII */ +- outbuf[buflen++] = 0; /* not officially assigned */ +- outbuf[buflen++] = 0; /* reserved */ +- outbuf[buflen++] = id_len; /* length of data following */ +- memcpy(outbuf + buflen, str, id_len); +- buflen += id_len; ++ if (id_len) { ++ outbuf[buflen++] = 0x2; /* ASCII */ ++ outbuf[buflen++] = 0; /* not officially assigned */ ++ outbuf[buflen++] = 0; /* reserved */ ++ outbuf[buflen++] = id_len; /* length of data following */ ++ memcpy(outbuf + buflen, str, id_len); ++ buflen += id_len; ++ } + + if (s->qdev.wwn) { + outbuf[buflen++] = 0x1; /* Binary */ +-- +1.8.3.1 + diff --git a/qemu-kvm.spec b/qemu-kvm.spec index 040639c..f08edde 100644 --- a/qemu-kvm.spec +++ b/qemu-kvm.spec @@ -174,6 +174,12 @@ Patch44: kvm-throttle-groups-fix-restart-coroutine-iothread-race.patch Patch45: kvm-iotests-add-238-for-throttling-tgm-unregister-iothre.patch # For bz#1668244 - qemu-img: /var/tmp/v2vovl9951f8.qcow2: CURL: Error opening file: The requested URL returned error: 404 Not Found Patch47: kvm-json-Fix-handling-when-not-interpolating.patch +# For bz#1665896 - VNC unix listener socket is deleted after first client quits +Patch48: kvm-io-ensure-UNIX-client-doesn-t-unlink-server-socket.patch +# For bz#1668248 - "An unknown error has occurred" when using cdrom to install the system with two blockdev disks.(when choose installation destination) +Patch49: kvm-scsi-disk-Don-t-use-empty-string-as-device-id.patch +# For bz#1668248 - "An unknown error has occurred" when using cdrom to install the system with two blockdev disks.(when choose installation destination) +Patch50: kvm-scsi-disk-Add-device_id-property.patch BuildRequires: zlib-devel BuildRequires: glib2-devel @@ -1021,8 +1027,15 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %changelog -* Thu Jan 31 2019 Danilo Cesar Lemes de Paula - 3.1.0-12.el8 +* Fri Feb 08 2019 Danilo Cesar Lemes de Paula - 3.1.0-12.el8 - Removing kvm-Fix-fsfreeze-hook-path-in-the-man-page.patch [bz#1644985] +- kvm-io-ensure-UNIX-client-doesn-t-unlink-server-socket.patch [bz#1665896] +- kvm-scsi-disk-Don-t-use-empty-string-as-device-id.patch [bz#1668248] +- kvm-scsi-disk-Add-device_id-property.patch [bz#1668248] +- Resolves: bz#1665896 + (VNC unix listener socket is deleted after first client quits) +- Resolves: bz#1668248 + ("An unknown error has occurred" when using cdrom to install the system with two blockdev disks.(when choose installation destination)) * Thu Jan 31 2019 Danilo Cesar Lemes de Paula - 3.1.0-11.el8 - kvm-Fix-fsfreeze-hook-path-in-the-man-page.patch [bz#1644985]