On Thu, Sep 21, 2023 at 03:58:05PM -0500, Eric Blake wrote:
As previous patches showed, the NBD spec does not yet forbid a
server
sending us a size that does not fit in int64_t. We should gracefully
handle this during nbdinfo, rather than giving up early.
With the same one-line hack to qemu to set the most significant bit of
the export size, output changes from pre-patch:
$ ./run nbdinfo nbd://localhost
/home/eblake/libnbd/info/.libs/nbdinfo: nbd_get_size: server claims size
9223372036854781440 which does not fit in signed result: Value too large for defined data
type
qemu-nbd: option negotiation failed: Failed to read opts magic: Unexpected end-of-file
before all data were read
to post-patch:
$ ./run nbdinfo nbd://localhost
protocol: newstyle-fixed without TLS, using extended packets
...
block_size_maximum: 33554432
or
$ ./run nbdinfo nbd://localhost --json
{
"protocol": "newstyle-fixed",
...
"block_size_maximum": 33554432,
"export-size-str": "unavailable"
} ]
}
Sadly, since writing a server with such large export sizes requires a
one-off hack, I don't see the point in adding a unit test.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
info/show.c | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/info/show.c b/info/show.c
index a71d837e..3d80545e 100644
--- a/info/show.c
+++ b/info/show.c
@@ -46,7 +46,7 @@ show_one_export (struct nbd_handle *nbd, const char *desc,
bool first, bool last)
{
int64_t i, size;
- char size_str[HUMAN_SIZE_LONGEST];
+ char size_str[HUMAN_SIZE_LONGEST] = "unavailable";
bool human_size_flag;
char *export_name = NULL;
char *export_desc = NULL;
@@ -89,13 +89,10 @@ show_one_export (struct nbd_handle *nbd, const char *desc,
return false;
}
size = nbd_get_size (nbd);
- if (size == -1) {
- fprintf (stderr, "%s: %s\n", progname, nbd_get_error ());
- exit (EXIT_FAILURE);
+ if (size >= 0) {
+ human_size (size_str, size, &human_size_flag);
}
- human_size (size_str, size, &human_size_flag);
-
if (uri_is_meaningful ())
uri = nbd_get_uri (nbd);
@@ -130,7 +127,8 @@ show_one_export (struct nbd_handle *nbd, const char *desc,
show_context = true;
/* Get content last, as it moves the connection out of negotiating */
- content = get_content (nbd, size);
+ if (size >= 0)
+ content = get_content (nbd, size);
if (!json_output) {
ansi_colour (ANSI_FG_BOLD_BLACK, fp);
@@ -140,10 +138,12 @@ show_one_export (struct nbd_handle *nbd, const char *desc,
fprintf (fp, ":\n");
if (desc && *desc)
fprintf (fp, "\tdescription: %s\n", desc);
- if (human_size_flag)
- fprintf (fp, "\texport-size: %" PRIi64 " (%s)\n", size,
size_str);
- else
- fprintf (fp, "\texport-size: %" PRIi64 "\n", size);
+ if (size >= 0) {
+ if (human_size_flag)
+ fprintf (fp, "\texport-size: %" PRIi64 " (%s)\n", size,
size_str);
+ else
+ fprintf (fp, "\texport-size: %" PRIi64 "\n", size);
+ }
if (content)
fprintf (fp, "\tcontent: %s\n", content);
if (uri)
@@ -273,7 +273,8 @@ show_one_export (struct nbd_handle *nbd, const char *desc,
block_maximum);
/* Put this one at the end because of the stupid comma thing in JSON. */
- fprintf (fp, "\t\"export-size\": %" PRIi64 ",\n",
size);
+ if (size >= 0)
+ fprintf (fp, "\t\"export-size\": %" PRIi64 ",\n",
size);
fprintf (fp, "\t\"export-size-str\": \"%s\"\n",
size_str);
if (last)
Reviewed-by: Richard W.M. Jones <rjones(a)redhat.com>
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
Read my programming and virtualization blog:
http://rwmj.wordpress.com
virt-builder quickly builds VMs from scratch
http://libguestfs.org/virt-builder.1.html