Skip to content

Commit

Permalink
qemu-img: Gracefully shutdown when map can't finish
Browse files Browse the repository at this point in the history
Trying 'qemu-img map -f raw nbd://localhost:10809' causes the
NBD server to output a scary message:

qemu-nbd: Disconnect client, due to: Failed to read request: Unexpected end-of-file before all bytes were read

This is because the NBD client, being remote, has no way to expose a
human-readable map (the --output=json data is fine, however). But
because we exit(1) right after the message, causing the client to
bypass all block cleanup, the server sees the abrupt exit and warns,
whereas it would be silent had the client had a chance to send
NBD_CMD_DISC. Other protocols may have similar cleanup issues, where
failure to blk_unref() could cause unintended effects.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20190326184043.7544-1-eblake@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
  • Loading branch information
ebblake committed Mar 30, 2019
1 parent ebd82cd commit 30065d1
Showing 1 changed file with 9 additions and 5 deletions.
14 changes: 9 additions & 5 deletions qemu-img.c
Expand Up @@ -2736,14 +2736,14 @@ static int img_info(int argc, char **argv)
return 0;
}

static void dump_map_entry(OutputFormat output_format, MapEntry *e,
MapEntry *next)
static int dump_map_entry(OutputFormat output_format, MapEntry *e,
MapEntry *next)
{
switch (output_format) {
case OFORMAT_HUMAN:
if (e->data && !e->has_offset) {
error_report("File contains external, encrypted or compressed clusters.");
exit(1);
return -1;
}
if (e->data && !e->zero) {
printf("%#-16"PRIx64"%#-16"PRIx64"%#-16"PRIx64"%s\n",
Expand Down Expand Up @@ -2776,6 +2776,7 @@ static void dump_map_entry(OutputFormat output_format, MapEntry *e,
}
break;
}
return 0;
}

static int get_block_status(BlockDriverState *bs, int64_t offset,
Expand Down Expand Up @@ -2968,12 +2969,15 @@ static int img_map(int argc, char **argv)
}

if (curr.length > 0) {
dump_map_entry(output_format, &curr, &next);
ret = dump_map_entry(output_format, &curr, &next);
if (ret < 0) {
goto out;
}
}
curr = next;
}

dump_map_entry(output_format, &curr, NULL);
ret = dump_map_entry(output_format, &curr, NULL);

out:
blk_unref(blk);
Expand Down

0 comments on commit 30065d1

Please sign in to comment.