aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2025-03-07 07:37:39 +0800
committerStefan Hajnoczi <stefanha@redhat.com>2025-03-07 07:37:39 +0800
commit3e61b839844334689cf46694ff1fd1624d6fae20 (patch)
tree6ee51e46a43944be8a078edc19989e80b06e037e
parente8a01102936286e012ed0f00bd7f3b7474d415c9 (diff)
parent3e1683485656c095860a8dfbe39ab2d0664b84d9 (diff)
downloadqemu-3e61b839844334689cf46694ff1fd1624d6fae20.zip
qemu-3e61b839844334689cf46694ff1fd1624d6fae20.tar.gz
qemu-3e61b839844334689cf46694ff1fd1624d6fae20.tar.bz2
Merge tag 'pull-nbd-2025-03-05' of https://repo.or.cz/qemu/ericb into staging
NBD patches for 2025-03-05 - Several iotest fixes - Refactor QMP for NbdServerOptions for less repetition - Avoid a hang in 'qemu-nbd --fork' when simple trace backend is enabled # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCAAdFiEEccLMIrHEYCkn0vOqp6FrSiUnQ2oFAmfI2I0ACgkQp6FrSiUn # Q2pMWQf/ZNnuLC5O5W4Yiyki7mYjN3Izve5+xgM/gNv9uTrHmYXogYzswpYz1USo # aU1i/EFLJ5K7ImefQYBvySox+opwFs63xPscI/liwrKu54csp1rYGNg3hjKYaZCc # ukR5tB4bRQ2/JXNo0JueiocMZLyC5fZRUt9Z423D3ReHCtEJof0v1rTL2r7mzGJg # EdaRSGr0s592rFjWLwwvWWun5f0mEAFXM2YvZRRLE7M+x2XJeAR4F400GfvSMDNo # chGX41QKhmCYTMI5Shc/mX+5hMllEt/TyYBJUUk0cslJriVnNDV5VTFf184BmH5s # tqiUtzJubxt8/Wtpg6OV9RPAzVmr1g== # =NO+l # -----END PGP SIGNATURE----- # gpg: Signature made Thu 06 Mar 2025 07:04:45 HKT # gpg: using RSA key 71C2CC22B1C4602927D2F3AAA7A16B4A2527436A # gpg: Good signature from "Eric Blake <eblake@redhat.com>" [full] # gpg: aka "Eric Blake (Free Software Programmer) <ebb9@byu.net>" [full] # gpg: aka "[jpeg image of size 6874]" [full] # Primary key fingerprint: 71C2 CC22 B1C4 6029 27D2 F3AA A7A1 6B4A 2527 436A * tag 'pull-nbd-2025-03-05' of https://repo.or.cz/qemu/ericb: nbd: Defer trace init until after daemonization qapi: merge common parts of NbdServerOptions and nbd-server-start data iotests: Stop NBD server in test 162 before starting the next one iotest: Unbreak 302 with python 3.13 Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-rw-r--r--blockdev-nbd.c4
-rw-r--r--qapi/block-export.json72
-rw-r--r--qemu-nbd.c16
-rwxr-xr-xtests/qemu-iotests/1621
-rwxr-xr-xtests/qemu-iotests/30219
5 files changed, 60 insertions, 52 deletions
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 3f6f4ef..1e3e634 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -219,12 +219,12 @@ void nbd_server_start_options(NbdServerOptions *arg, Error **errp)
arg->tls_authz, arg->max_connections, errp);
}
-void qmp_nbd_server_start(SocketAddressLegacy *addr,
- bool has_handshake_max_secs,
+void qmp_nbd_server_start(bool has_handshake_max_secs,
uint32_t handshake_max_secs,
const char *tls_creds,
const char *tls_authz,
bool has_max_connections, uint32_t max_connections,
+ SocketAddressLegacy *addr,
Error **errp)
{
SocketAddress *addr_flat = socket_address_flatten(addr);
diff --git a/qapi/block-export.json b/qapi/block-export.json
index 68dcec7..c783e01 100644
--- a/qapi/block-export.json
+++ b/qapi/block-export.json
@@ -9,17 +9,11 @@
{ 'include': 'block-core.json' }
##
-# @NbdServerOptions:
-#
-# Keep this type consistent with the nbd-server-start arguments. The
-# only intended difference is using SocketAddress instead of
-# SocketAddressLegacy.
-#
-# @addr: Address on which to listen.
+# @NbdServerOptionsBase:
#
# @handshake-max-seconds: Time limit, in seconds, at which a client
# that has not completed the negotiation handshake will be
-# disconnected, 0 for no limit (since 10.0; default: 10).
+# disconnected, or 0 for no limit (since 10.0; default: 10).
#
# @tls-creds: ID of the TLS credentials object (since 2.6).
#
@@ -32,47 +26,47 @@
# @max-connections: The maximum number of connections to allow at the
# same time, 0 for unlimited. Setting this to 1 also stops the
# server from advertising multiple client support (since 5.2;
-# default: 100)
-#
-# Since: 4.2
+# default: 100).
##
-{ 'struct': 'NbdServerOptions',
- 'data': { 'addr': 'SocketAddress',
- '*handshake-max-seconds': 'uint32',
+{ 'struct': 'NbdServerOptionsBase',
+ 'data': { '*handshake-max-seconds': 'uint32',
'*tls-creds': 'str',
'*tls-authz': 'str',
'*max-connections': 'uint32' } }
##
-# @nbd-server-start:
+# @NbdServerOptions:
#
-# Start an NBD server listening on the given host and port. Block
-# devices can then be exported using @nbd-server-add. The NBD server
-# will present them as named exports; for example, another QEMU
-# instance could refer to them as "nbd:HOST:PORT:exportname=NAME".
+# Keep this type consistent with the NbdServerOptionsLegacy type. The
+# only intended difference is using SocketAddress instead of
+# SocketAddressLegacy.
+#
+# @addr: Address on which to listen (since 4.2).
+##
+{ 'struct': 'NbdServerOptions',
+ 'base': 'NbdServerOptionsBase',
+ 'data': { 'addr': 'SocketAddress' } }
+
+##
+# @NbdServerOptionsLegacy:
#
# Keep this type consistent with the NbdServerOptions type. The only
# intended difference is using SocketAddressLegacy instead of
# SocketAddress.
#
-# @addr: Address on which to listen.
-#
-# @handshake-max-seconds: Time limit, in seconds, at which a client
-# that has not completed the negotiation handshake will be
-# disconnected, or 0 for no limit (since 10.0; default: 10).
-#
-# @tls-creds: ID of the TLS credentials object (since 2.6).
-#
-# @tls-authz: ID of the QAuthZ authorization object used to validate
-# the client's x509 distinguished name. This object is is only
-# resolved at time of use, so can be deleted and recreated on the
-# fly while the NBD server is active. If missing, it will default
-# to denying access (since 4.0).
+# @addr: Address on which to listen (since 1.3).
+##
+{ 'struct': 'NbdServerOptionsLegacy',
+ 'base': 'NbdServerOptionsBase',
+ 'data': { 'addr': 'SocketAddressLegacy' } }
+
+##
+# @nbd-server-start:
#
-# @max-connections: The maximum number of connections to allow at the
-# same time, 0 for unlimited. Setting this to 1 also stops the
-# server from advertising multiple client support (since 5.2;
-# default: 100).
+# Start an NBD server listening on the given host and port. Block
+# devices can then be exported using @nbd-server-add. The NBD server
+# will present them as named exports; for example, another QEMU
+# instance could refer to them as "nbd:HOST:PORT:exportname=NAME".
#
# Errors:
# - if the server is already running
@@ -80,11 +74,7 @@
# Since: 1.3
##
{ 'command': 'nbd-server-start',
- 'data': { 'addr': 'SocketAddressLegacy',
- '*handshake-max-seconds': 'uint32',
- '*tls-creds': 'str',
- '*tls-authz': 'str',
- '*max-connections': 'uint32' },
+ 'data': 'NbdServerOptionsLegacy',
'allow-preconfig': true }
##
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 05b61da..ed58958 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -852,10 +852,6 @@ int main(int argc, char **argv)
export_name = "";
}
- if (!trace_init_backends()) {
- exit(1);
- }
- trace_init_file();
qemu_set_log(LOG_TRACE, &error_fatal);
socket_activation = check_socket_activation();
@@ -1045,6 +1041,18 @@ int main(int argc, char **argv)
#endif /* WIN32 */
}
+ /*
+ * trace_init must be done after daemonization. Why? Because at
+ * least the simple backend spins up a helper thread as well as an
+ * atexit() handler that waits on that thread, but the helper
+ * thread won't survive a fork, leading to deadlock in the child
+ * if we initialized pre-fork.
+ */
+ if (!trace_init_backends()) {
+ exit(1);
+ }
+ trace_init_file();
+
if (opts.device != NULL && sockpath == NULL) {
sockpath = g_malloc(128);
snprintf(sockpath, 128, SOCKET_PATH, basename(opts.device));
diff --git a/tests/qemu-iotests/162 b/tests/qemu-iotests/162
index 94dae60..956c2c5 100755
--- a/tests/qemu-iotests/162
+++ b/tests/qemu-iotests/162
@@ -65,6 +65,7 @@ done
$QEMU_IMG info "json:{'driver': 'nbd', 'host': 'localhost', 'port': $port}" \
| grep '^image' | sed -e "s/$port/PORT/"
+_stop_nbd_server
# This is a test for NBD's bdrv_refresh_filename() implementation: It expects
# either host or path to be set, but it must not assume that they are set to
diff --git a/tests/qemu-iotests/302 b/tests/qemu-iotests/302
index a6d79e7..e980ec5 100755
--- a/tests/qemu-iotests/302
+++ b/tests/qemu-iotests/302
@@ -115,13 +115,22 @@ with tarfile.open(tar_file, "w") as tar:
disk = tarfile.TarInfo("disk")
disk.size = actual_size
- tar.addfile(disk)
- # 6. Shrink the tar to the actual size, aligned to 512 bytes.
+ # Since python 3.13 we cannot use addfile() to create the member header.
+ # Add the tarinfo directly using public but undocumented attributes.
- tar_size = offset + (disk.size + 511) & ~511
- tar.fileobj.seek(tar_size)
- tar.fileobj.truncate(tar_size)
+ buf = disk.tobuf(tar.format, tar.encoding, tar.errors)
+ tar.fileobj.write(buf)
+ tar.members.append(disk)
+
+ # Update the offset and position to the location of the next member.
+
+ tar.offset = offset + (disk.size + 511) & ~511
+ tar.fileobj.seek(tar.offset)
+
+ # 6. Shrink the tar to the actual size.
+
+ tar.fileobj.truncate(tar.offset)
with tarfile.open(tar_file) as tar:
members = [{"name": m.name, "size": m.size, "offset": m.offset_data}