We always advertise this to the client (for writable exports), even when the plugin does not have any optimized implementation, because it allows for more efficient network traffic.
Signed-off-by: Eric Blake <ebl...@redhat.com> --- src/connections.c | 26 ++++++++++++++++++++++++-- src/protocol.h | 17 ++++++++++------- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/connections.c b/src/connections.c index 44b7530..1b39547 100644 --- a/src/connections.c +++ b/src/connections.c @@ -180,6 +180,10 @@ _negotiate_handshake_oldstyle (struct connection *conn) eflags |= NBD_FLAG_READ_ONLY; conn->readonly = 1; } + if (!conn->readonly) { + eflags |= NBD_FLAG_SEND_WRITE_ZEROES; + } + fl = plugin_can_flush (conn); if (fl == -1) @@ -442,6 +446,9 @@ _negotiate_handshake_newstyle (struct connection *conn) eflags |= NBD_FLAG_READ_ONLY; conn->readonly = 1; } + if (!conn->readonly) { + eflags |= NBD_FLAG_SEND_WRITE_ZEROES; + } fl = plugin_can_flush (conn); if (fl == -1) @@ -520,6 +527,7 @@ validate_request (struct connection *conn, case NBD_CMD_READ: case NBD_CMD_WRITE: case NBD_CMD_TRIM: + case NBD_CMD_WRITE_ZEROES: r = valid_range (conn, offset, count); if (r == -1) return -1; @@ -547,11 +555,17 @@ validate_request (struct connection *conn, } /* Validate flags */ - if (flags & ~NBD_CMD_FLAG_FUA) { + if (flags & ~(NBD_CMD_FLAG_FUA | NBD_CMD_FLAG_NO_HOLE)) { nbdkit_error ("invalid request: unknown flag (0x%x)", flags); *error = EINVAL; return 0; } + if ((flags & NBD_CMD_FLAG_NO_HOLE) && + cmd != NBD_CMD_WRITE_ZEROES) { + nbdkit_error ("invalid request: NO_HOLE flag needs WRITE_ZEROES request"); + *error = EINVAL; + return 0; + } /* Refuse over-large read and write requests. */ if ((cmd == NBD_CMD_WRITE || cmd == NBD_CMD_READ) && @@ -565,7 +579,7 @@ validate_request (struct connection *conn, /* Readonly connection? */ if (conn->readonly && (cmd == NBD_CMD_WRITE || cmd == NBD_CMD_FLUSH || - cmd == NBD_CMD_TRIM)) { + cmd == NBD_CMD_TRIM || cmd == NBD_CMD_WRITE_ZEROES)) { nbdkit_error ("invalid request: write request on readonly connection"); *error = EROFS; return 0; @@ -647,6 +661,14 @@ _handle_request (struct connection *conn, } break; + case NBD_CMD_WRITE_ZEROES: + r = plugin_zero (conn, count, offset, !(flags & NBD_CMD_FLAG_NO_HOLE)); + if (r == -1) { + *error = errno ? errno : EIO; + return 0; + } + break; + default: abort (); } diff --git a/src/protocol.h b/src/protocol.h index 23630a9..4571a3a 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -87,12 +87,13 @@ struct new_handshake_finish { #define NBD_FLAG_NO_ZEROES 2 /* Per-export flags. */ -#define NBD_FLAG_HAS_FLAGS 1 -#define NBD_FLAG_READ_ONLY 2 -#define NBD_FLAG_SEND_FLUSH 4 -#define NBD_FLAG_SEND_FUA 8 -#define NBD_FLAG_ROTATIONAL 16 -#define NBD_FLAG_SEND_TRIM 32 +#define NBD_FLAG_HAS_FLAGS (1 << 0) +#define NBD_FLAG_READ_ONLY (1 << 1) +#define NBD_FLAG_SEND_FLUSH (1 << 2) +#define NBD_FLAG_SEND_FUA (1 << 3) +#define NBD_FLAG_ROTATIONAL (1 << 4) +#define NBD_FLAG_SEND_TRIM (1 << 5) +#define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* NBD options (new style handshake only). */ #define NBD_OPT_EXPORT_NAME 1 @@ -130,8 +131,10 @@ struct reply { #define NBD_CMD_DISC 2 /* Disconnect. */ #define NBD_CMD_FLUSH 3 #define NBD_CMD_TRIM 4 +#define NBD_CMD_WRITE_ZEROES 6 #define NBD_CMD_MASK_COMMAND 0xffff -#define NBD_CMD_FLAG_FUA (1<<16) +#define NBD_CMD_FLAG_FUA (1<<16) +#define NBD_CMD_FLAG_NO_HOLE (2<<16) /* Error codes (previously errno). * See http://git.qemu.org/?p=qemu.git;a=commitdiff;h=ca4414804114fd0095b317785bc0b51862e62ebb -- 2.9.3 _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://www.redhat.com/mailman/listinfo/libguestfs