From f141228d1b6baddadcd516137d76b3d852af8cde Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 12 Jan 2016 12:16:48 +0000 Subject: [PATCH 07/10] protocol: Send limited range of errno values to the client. See the proposal here: http://article.gmane.org/gmane.linux.drivers.nbd.general/3154 This implementation is based on Paolo Bonzini's for qemu-nbd: http://git.qemu.org/?p=qemu.git;a=commitdiff;h=ca4414804114fd0095b317785bc0b51862e62ebb --- TODO | 6 ------ src/connections.c | 36 +++++++++++++++++++++++++++++++++++- src/protocol.h | 12 +++++++++++- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/TODO b/TODO index d39e64c..177a07c 100644 --- a/TODO +++ b/TODO @@ -1,9 +1,3 @@ -* There is a proposal to narrow the range of possible errnos that the - server can return, and also to encode them in an OS-independent way. - See: http://article.gmane.org/gmane.linux.drivers.nbd.general/3154 - Implemented in QEMU already: - http://git.qemu.org/?p=qemu.git;a=commitdiff;h=ca4414804114fd0095b317785bc0b51862e62ebb - * Can we do language bindings using #!'s? You would enter: nbdkit foo [args] diff --git a/src/connections.c b/src/connections.c index 6bdf4ef..f0a7662 100644 --- a/src/connections.c +++ b/src/connections.c @@ -639,6 +639,31 @@ skip_over_write_buffer (int sock, size_t count) } } +/* Convert a system errno to an NBD_E* error code. */ +static int +nbd_errno (int error) +{ + switch (error) { + case 0: + return NBD_SUCCESS; + case EPERM: + return NBD_EPERM; + case EIO: + return NBD_EIO; + case ENOMEM: + return NBD_ENOMEM; +#ifdef EDQUOT + case EDQUOT: +#endif + case EFBIG: + case ENOSPC: + return NBD_ENOSPC; + case EINVAL: + default: + return NBD_EINVAL; + } +} + static int recv_request_send_reply (struct connection *conn) { @@ -722,7 +747,16 @@ recv_request_send_reply (struct connection *conn) send_reply: reply.magic = htobe32 (NBD_REPLY_MAGIC); reply.handle = request.handle; - reply.error = htobe32 (error); + reply.error = htobe32 (nbd_errno (error)); + + if (error != 0) { + /* Since we're about to send only the limited NBD_E* errno to the + * client, don't lose the information about what really happened + * on the server side. Make sure there is a way for the operator + * to retrieve the real error. + */ + debug ("sending error reply: %s", strerror (error)); + } r = xwrite (conn->sockout, &reply, sizeof reply); if (r == -1) { diff --git a/src/protocol.h b/src/protocol.h index 2f9a341..fcbc145 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -118,7 +118,7 @@ struct request { /* Reply (server -> client). */ struct reply { uint32_t magic; /* NBD_REPLY_MAGIC. */ - uint32_t error; /* 0 = ok, error code */ + uint32_t error; /* NBD_SUCCESS or one of NBD_E*. */ uint64_t handle; /* Opaque handle. */ } __attribute__((packed)); @@ -133,4 +133,14 @@ struct reply { #define NBD_CMD_MASK_COMMAND 0xffff #define NBD_CMD_FLAG_FUA (1<<16) +/* Error codes (previously errno). + * See http://git.qemu.org/?p=qemu.git;a=commitdiff;h=ca4414804114fd0095b317785bc0b51862e62ebb + */ +#define NBD_SUCCESS 0 +#define NBD_EPERM 1 +#define NBD_EIO 5 +#define NBD_ENOMEM 12 +#define NBD_EINVAL 22 +#define NBD_ENOSPC 28 + #endif /* NBDKIT_PROTOCOL_H */ -- 2.7.4