server: Better newstyle .open failure handling
commite60d67ee9f3bb927afd57fb20854f448cc6eb433
authorEric Blake <eblake@redhat.com>
Wed, 25 Sep 2019 15:58:18 +0000 (25 10:58 -0500)
committerEric Blake <eblake@redhat.com>
Mon, 30 Sep 2019 21:29:47 +0000 (30 16:29 -0500)
tree00c10f3a3d78577d88aecb260b76e5da8be3f9cd
parent20b8509a9ccdab118ce7b7043be63bbad74f1e79
server: Better newstyle .open failure handling

If a plugin's .open or .get_size or .can_write fails, right now that
is fatal to the connection.  When nbdkit was first implemented, this
made sense (there was no way to report errors to oldstyle or
NBD_OPT_EXPORT_NAME).  But now that newstyle is around, it's rather
abrupt to hang up on the client, and better is to return an error to
NBD_OPT_GO, and let the client choose what to do (most clients will
probably hang up, whether gracefully with NBD_OPT_ABORT or abruptly,
rather than try other NBD_OPT_*, but _we_ shouldn't be the ones
forcing their hand).

For an example of what this improves, if you run:

$ nbdkit -fv sh - <<\EOF
case $1 in get_size) echo oops >&2; exit 1;; *) exit 2;; esac
EOF

Pre-patch, qemu complains about the abrupt server death:
$ qemu-nbd --list
qemu-nbd: Failed to read option reply: Unexpected end-of-file before all bytes were read

Post-patch, qemu gets the desired error message, and exits gracefully:
$ qemu-nbd --list
qemu-nbd: Requested export not available

Note that this does not fix the pre-existing problem that we can end
up calling .finalize even when .prepare was skipped or failed (that
latent problem was first exposed for the rare client that calls
NBD_OPT_INFO before NBD_OPT_GO, see commit a6b88b19); a later patch
will have to add better bookkeeping for that, and for better handling
of reopen requests from the retry filter.

Signed-off-by: Eric Blake <eblake@redhat.com>
server/protocol-handshake-newstyle.c
server/protocol-handshake-oldstyle.c