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-----

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>
This commit is contained in:
Stefan Hajnoczi 2025-03-07 07:37:39 +08:00
commit 3e61b83984
5 changed files with 71 additions and 63 deletions

View file

@ -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);

View file

@ -9,53 +9,7 @@
{ '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.
#
# @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).
#
# @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).
#
# @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
##
{ 'struct': 'NbdServerOptions',
'data': { 'addr': 'SocketAddress',
'*handshake-max-seconds': 'uint32',
'*tls-creds': 'str',
'*tls-authz': 'str',
'*max-connections': 'uint32' } }
##
# @nbd-server-start:
#
# 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 NbdServerOptions type. The only
# intended difference is using SocketAddressLegacy instead of
# SocketAddress.
#
# @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
@ -73,6 +27,46 @@
# same time, 0 for unlimited. Setting this to 1 also stops the
# server from advertising multiple client support (since 5.2;
# default: 100).
##
{ 'struct': 'NbdServerOptionsBase',
'data': { '*handshake-max-seconds': 'uint32',
'*tls-creds': 'str',
'*tls-authz': 'str',
'*max-connections': 'uint32' } }
##
# @NbdServerOptions:
#
# 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 (since 1.3).
##
{ 'struct': 'NbdServerOptionsLegacy',
'base': 'NbdServerOptionsBase',
'data': { 'addr': 'SocketAddressLegacy' } }
##
# @nbd-server-start:
#
# 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 }
##

View file

@ -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));

View file

@ -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

View file

@ -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}