nbd: Prepare for NBD_CMD_FLAG_FAST_ZERO

Commit fe0480d6 and friends added BDRV_REQ_NO_FALLBACK as a way to
avoid wasting time on a preliminary write-zero request that will later
be rewritten by actual data, if it is known that the write-zero
request will use a slow fallback; but in doing so, could not optimize
for NBD.  The NBD specification is now considering an extension that
will allow passing on those semantics; this patch updates the new
protocol bits and 'qemu-nbd --list' output to recognize the bit, as
well as the new errno value possible when using the new flag; while
upcoming patches will improve the client to use the feature when
present, and the server to advertise support for it.

The NBD spec recommends (but not requires) that ENOTSUP be avoided for
all but failures of a fast zero (the only time it is mandatory to
avoid an ENOTSUP failure is when fast zero is supported but not
requested during write zeroes; the questionable use is for ENOTSUP to
other actions like a normal write request).  However, clients that get
an unexpected ENOTSUP will either already be treating it the same as
EINVAL, or may appreciate the extra bit of information.  We were
equally loose for returning EOVERFLOW in more situations than
recommended by the spec, so if it turns out to be a problem in
practice, a later patch can tighten handling for both error codes.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20190823143726.27062-3-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
[eblake: tweak commit message, also handle EOPNOTSUPP]
This commit is contained in:
Eric Blake 2019-08-23 09:37:23 -05:00
parent dbb38caac5
commit 0a4795455c
5 changed files with 17 additions and 1 deletions

View File

@ -53,4 +53,5 @@ the operation of that feature.
* 2.12: NBD_CMD_BLOCK_STATUS for "base:allocation" * 2.12: NBD_CMD_BLOCK_STATUS for "base:allocation"
* 3.0: NBD_OPT_STARTTLS with TLS Pre-Shared Keys (PSK), * 3.0: NBD_OPT_STARTTLS with TLS Pre-Shared Keys (PSK),
NBD_CMD_BLOCK_STATUS for "qemu:dirty-bitmap:", NBD_CMD_CACHE NBD_CMD_BLOCK_STATUS for "qemu:dirty-bitmap:", NBD_CMD_CACHE
* 4.2: NBD_FLAG_CAN_MULTI_CONN for sharable read-only exports * 4.2: NBD_FLAG_CAN_MULTI_CONN for sharable read-only exports,
NBD_CMD_FLAG_FAST_ZERO

View File

@ -140,6 +140,7 @@ enum {
NBD_FLAG_CAN_MULTI_CONN_BIT = 8, /* Multi-client cache consistent */ NBD_FLAG_CAN_MULTI_CONN_BIT = 8, /* Multi-client cache consistent */
NBD_FLAG_SEND_RESIZE_BIT = 9, /* Send resize */ NBD_FLAG_SEND_RESIZE_BIT = 9, /* Send resize */
NBD_FLAG_SEND_CACHE_BIT = 10, /* Send CACHE (prefetch) */ NBD_FLAG_SEND_CACHE_BIT = 10, /* Send CACHE (prefetch) */
NBD_FLAG_SEND_FAST_ZERO_BIT = 11, /* FAST_ZERO flag for WRITE_ZEROES */
}; };
#define NBD_FLAG_HAS_FLAGS (1 << NBD_FLAG_HAS_FLAGS_BIT) #define NBD_FLAG_HAS_FLAGS (1 << NBD_FLAG_HAS_FLAGS_BIT)
@ -153,6 +154,7 @@ enum {
#define NBD_FLAG_CAN_MULTI_CONN (1 << NBD_FLAG_CAN_MULTI_CONN_BIT) #define NBD_FLAG_CAN_MULTI_CONN (1 << NBD_FLAG_CAN_MULTI_CONN_BIT)
#define NBD_FLAG_SEND_RESIZE (1 << NBD_FLAG_SEND_RESIZE_BIT) #define NBD_FLAG_SEND_RESIZE (1 << NBD_FLAG_SEND_RESIZE_BIT)
#define NBD_FLAG_SEND_CACHE (1 << NBD_FLAG_SEND_CACHE_BIT) #define NBD_FLAG_SEND_CACHE (1 << NBD_FLAG_SEND_CACHE_BIT)
#define NBD_FLAG_SEND_FAST_ZERO (1 << NBD_FLAG_SEND_FAST_ZERO_BIT)
/* New-style handshake (global) flags, sent from server to client, and /* New-style handshake (global) flags, sent from server to client, and
control what will happen during handshake phase. */ control what will happen during handshake phase. */
@ -205,6 +207,7 @@ enum {
#define NBD_CMD_FLAG_DF (1 << 2) /* don't fragment structured read */ #define NBD_CMD_FLAG_DF (1 << 2) /* don't fragment structured read */
#define NBD_CMD_FLAG_REQ_ONE (1 << 3) /* only one extent in BLOCK_STATUS #define NBD_CMD_FLAG_REQ_ONE (1 << 3) /* only one extent in BLOCK_STATUS
* reply chunk */ * reply chunk */
#define NBD_CMD_FLAG_FAST_ZERO (1 << 4) /* fail if WRITE_ZEROES is not fast */
/* Supported request types */ /* Supported request types */
enum { enum {
@ -270,6 +273,7 @@ static inline bool nbd_reply_type_is_error(int type)
#define NBD_EINVAL 22 #define NBD_EINVAL 22
#define NBD_ENOSPC 28 #define NBD_ENOSPC 28
#define NBD_EOVERFLOW 75 #define NBD_EOVERFLOW 75
#define NBD_ENOTSUP 95
#define NBD_ESHUTDOWN 108 #define NBD_ESHUTDOWN 108
/* Details collected by NBD_OPT_EXPORT_NAME and NBD_OPT_GO */ /* Details collected by NBD_OPT_EXPORT_NAME and NBD_OPT_GO */

View File

@ -201,6 +201,8 @@ const char *nbd_err_lookup(int err)
return "ENOSPC"; return "ENOSPC";
case NBD_EOVERFLOW: case NBD_EOVERFLOW:
return "EOVERFLOW"; return "EOVERFLOW";
case NBD_ENOTSUP:
return "ENOTSUP";
case NBD_ESHUTDOWN: case NBD_ESHUTDOWN:
return "ESHUTDOWN"; return "ESHUTDOWN";
default: default:
@ -231,6 +233,9 @@ int nbd_errno_to_system_errno(int err)
case NBD_EOVERFLOW: case NBD_EOVERFLOW:
ret = EOVERFLOW; ret = EOVERFLOW;
break; break;
case NBD_ENOTSUP:
ret = ENOTSUP;
break;
case NBD_ESHUTDOWN: case NBD_ESHUTDOWN:
ret = ESHUTDOWN; ret = ESHUTDOWN;
break; break;

View File

@ -55,6 +55,11 @@ static int system_errno_to_nbd_errno(int err)
return NBD_ENOSPC; return NBD_ENOSPC;
case EOVERFLOW: case EOVERFLOW:
return NBD_EOVERFLOW; return NBD_EOVERFLOW;
case ENOTSUP:
#if ENOTSUP != EOPNOTSUPP
case EOPNOTSUPP:
#endif
return NBD_ENOTSUP;
case ESHUTDOWN: case ESHUTDOWN:
return NBD_ESHUTDOWN; return NBD_ESHUTDOWN;
case EINVAL: case EINVAL:

View File

@ -294,6 +294,7 @@ static int qemu_nbd_client_list(SocketAddress *saddr, QCryptoTLSCreds *tls,
[NBD_FLAG_CAN_MULTI_CONN_BIT] = "multi", [NBD_FLAG_CAN_MULTI_CONN_BIT] = "multi",
[NBD_FLAG_SEND_RESIZE_BIT] = "resize", [NBD_FLAG_SEND_RESIZE_BIT] = "resize",
[NBD_FLAG_SEND_CACHE_BIT] = "cache", [NBD_FLAG_SEND_CACHE_BIT] = "cache",
[NBD_FLAG_SEND_FAST_ZERO_BIT] = "fast-zero",
}; };
printf(" size: %" PRIu64 "\n", list[i].size); printf(" size: %" PRIu64 "\n", list[i].size);