[Libguestfs] [nbdkit PATCH 4/5] protocol: Implement NBD_CMD_WRITE_ZEROES

Eric Blake eblake at redhat.com
Fri Jan 20 20:16:21 UTC 2017


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 <eblake at 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




More information about the Libguestfs mailing list