This sends the last error saved in the connection handle back to the NBD client. This is informational and best effort.
qemu reports the error already, for example: $ nbdkit --log=null \ eval open=' echo EPERM Go Away >&2; exit 1 ' get_size=' echo 100 ' \ --run 'qemu-img info "$uri"' qemu-img: Could not open 'nbd+unix://?socket=/tmp/nbdkitIDl6iy/socket': Requested export not available server reported: /tmp/nbdkitRDAfXH/open: Go Away This goes back to at least qemu 2.12.0 (RHEL 7) and possibly earlier, so we can just assume that qemu does this for the test. libnbd requires a patch to display this information. --- tests/Makefile.am | 2 + server/protocol-handshake-newstyle.c | 22 ++++++++++- tests/test-last-error.sh | 55 ++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 8c7d6b8c96..89c5fa9d0f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -292,6 +292,7 @@ TESTS += \ test-read-password-interactive.sh \ test-nbd-client.sh \ test-nbd-client-tls.sh \ + test-last-error.sh \ $(NULL) if !IS_WINDOWS TESTS += \ @@ -324,6 +325,7 @@ EXTRA_DIST += \ test-help-plugin.sh \ test-ipv4-lo.sh \ test-ipv6-lo.sh \ + test-last-error.sh \ test-long-name.sh \ test-nbd-client-tls.sh \ test-nbd-client.sh \ diff --git a/server/protocol-handshake-newstyle.c b/server/protocol-handshake-newstyle.c index 6b3bc76f0f..46cd0328b1 100644 --- a/server/protocol-handshake-newstyle.c +++ b/server/protocol-handshake-newstyle.c @@ -57,16 +57,32 @@ send_newstyle_option_reply (uint32_t option, uint32_t reply) { GET_CONN; struct nbd_fixed_new_option_reply fixed_new_option_reply; + const char *last_error = NULL; + uint32_t replylen = 0; + + if (NBD_REP_IS_ERR (reply)) { + last_error = threadlocal_get_last_error (); + /* Note that calling nbdkit_error will invalidate last_error, so + * be careful below. + */ + if (last_error) { + size_t len = strlen (last_error); + if (len <= NBD_MAX_STRING) + replylen = len; + } + } fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC); fixed_new_option_reply.option = htobe32 (option); fixed_new_option_reply.reply = htobe32 (reply); - fixed_new_option_reply.replylen = htobe32 (0); + fixed_new_option_reply.replylen = htobe32 (replylen); debug ("replying to %s with %s", name_of_nbd_opt (option), name_of_nbd_rep (reply)); if (conn->send (&fixed_new_option_reply, - sizeof fixed_new_option_reply, 0) == -1) { + sizeof fixed_new_option_reply, + replylen > 0 ? SEND_MORE : 0) == -1) { + err: /* The protocol document says that the client is allowed to simply * drop the connection after sending NBD_OPT_ABORT, or may read * the reply. @@ -77,6 +93,8 @@ send_newstyle_option_reply (uint32_t option, uint32_t reply) nbdkit_error ("write: %s: %m", name_of_nbd_opt (option)); return -1; } + if (replylen > 0 && conn->send (last_error, replylen, 0) == -1) + goto err; return 0; } diff --git a/tests/test-last-error.sh b/tests/test-last-error.sh new file mode 100755 index 0000000000..fc720606d9 --- /dev/null +++ b/tests/test-last-error.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# nbdkit +# Copyright Red Hat +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Red Hat nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +source ./functions.sh +set -e +set -x + +# Test informational error messages sent to the NBD client. +# qemu-img supports this since at least 2.12.0. + +requires_run +requires_plugin eval +requires qemu-img --version + +out=last-error.out +rm -f $out +cleanup_fn rm -f $out + +export out + +nbdkit eval \ + open=' echo EPERM Go Away >&2; exit 1 ' get_size=' echo 0 ' \ + --run ' qemu-img info "$uri" > $out 2>&1 ||: ' +cat $out + +grep "Go Away" $out -- 2.44.0 _______________________________________________ Libguestfs mailing list -- guestfs@lists.libguestfs.org To unsubscribe send an email to guestfs-le...@lists.libguestfs.org