Skip to contentSkip to conversation

nbd/server: introduce NBD_CMD_CACHE

PATCH In review Vladimir Sementsov-Ogievskiy 2 participants 10 messages Apr 13, 2018 – Jun 21, 2018

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 nbd/server: introduce NBD_CMD_CACHE

Handle nbd CACHE command. Just do read, without sending read data back. Cache mechanism should be done by exported node driver chain.

---
 include/block/nbd.h |  3 ++-
 nbd/server.c        | 10 ++++++----
 2 files changed, 8 insertions(+), 5 deletions(-)
include/block/nbd.h +2 -1
index fcdcd54502..b4793d0a29 100644
@@ -135,6 +135,7 @@ typedef struct NBDExtent {
 #define NBD_FLAG_SEND_TRIM         (1 << 5) /* Send TRIM (discard) */
 #define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send WRITE_ZEROES */
 #define NBD_FLAG_SEND_DF           (1 << 7) /* Send DF (Do not Fragment) */
+#define NBD_FLAG_SEND_CACHE        (1 << 8) /* Send CACHE (prefetch) */
 
 /* New-style handshake (global) flags, sent from server to client, and
    control what will happen during handshake phase. */
@@ -195,7 +196,7 @@ enum {
     NBD_CMD_DISC = 2,
     NBD_CMD_FLUSH = 3,
     NBD_CMD_TRIM = 4,
-    /* 5 reserved for failed experiment NBD_CMD_CACHE */
+    NBD_CMD_CACHE = 5,
     NBD_CMD_WRITE_ZEROES = 6,
     NBD_CMD_BLOCK_STATUS = 7,
 };
nbd/server.c +6 -4
index 9e1f227178..30d7d3f444 100644
@@ -1134,7 +1134,7 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
     int ret;
     const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
                               NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA |
-                              NBD_FLAG_SEND_WRITE_ZEROES);
+                              NBD_FLAG_SEND_WRITE_ZEROES | NBD_FLAG_SEND_CACHE);
     bool oldStyle;
 
     /* Old style negotiation header, no room for options
@@ -1826,7 +1826,9 @@ static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
         return -EIO;
     }
 
-    if (request->type == NBD_CMD_READ || request->type == NBD_CMD_WRITE) {
+    if (request->type == NBD_CMD_READ || request->type == NBD_CMD_WRITE ||
+        request->type == NBD_CMD_CACHE)
+    {
         if (request->len > NBD_MAX_BUFFER_SIZE) {
             error_setg(errp, "len (%" PRIu32" ) is larger than max len (%u)",
                        request->len, NBD_MAX_BUFFER_SIZE);
@@ -1911,7 +1913,7 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
     int ret;
     NBDExport *exp = client->exp;
 
-    assert(request->type == NBD_CMD_READ);
+    assert(request->type == NBD_CMD_READ || request->type == NBD_CMD_CACHE);
 
     /* XXX: NBD Protocol only documents use of FUA with WRITE */
     if (request->flags & NBD_CMD_FLAG_FUA) {
@@ -1930,7 +1932,7 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
 
     ret = blk_pread(exp->blk, request->from + exp->dev_offset, data,
                     request->len);
-    if (ret < 0) {
+    if (ret < 0 || request->type == NBD_CMD_CACHE) {
         return nbd_send_generic_reply(client, request->handle, ret,
                                       "reading from file failed", errp);
     }
Signature · 1 line
2.11.1
#1 lore raw
Quoted 64 lines · Vladimir Sementsov-Ogievskiy

Handle nbd CACHE command. Just do read, without sending read data back. Cache mechanism should be done by exported node driver chain.

---
  include/block/nbd.h |  3 ++-
  nbd/server.c        | 10 ++++++----
  2 files changed, 8 insertions(+), 5 deletions(-)
include/block/nbd.h +2 -1
index fcdcd54502..b4793d0a29 100644
@@ -135,6 +135,7 @@ typedef struct NBDExtent {
  #define NBD_FLAG_SEND_TRIM         (1 << 5) /* Send TRIM (discard) */
  #define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send WRITE_ZEROES */
  #define NBD_FLAG_SEND_DF           (1 << 7) /* Send DF (Do not Fragment) */
+#define NBD_FLAG_SEND_CACHE        (1 << 8) /* Send CACHE (prefetch) */
 
  /* New-style handshake (global) flags, sent from server to client, and
     control what will happen during handshake phase. */
@@ -195,7 +196,7 @@ enum {
      NBD_CMD_DISC = 2,
      NBD_CMD_FLUSH = 3,
      NBD_CMD_TRIM = 4,
-    /* 5 reserved for failed experiment NBD_CMD_CACHE */
+    NBD_CMD_CACHE = 5,
      NBD_CMD_WRITE_ZEROES = 6,
      NBD_CMD_BLOCK_STATUS = 7,
  };
nbd/server.c +5 -3
index 9e1f227178..30d7d3f444 100644
@@ -1134,7 +1134,7 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
      int ret;
      const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
                                NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA |
-                              NBD_FLAG_SEND_WRITE_ZEROES);
+                              NBD_FLAG_SEND_WRITE_ZEROES | NBD_FLAG_SEND_CACHE);
      bool oldStyle;
 
      /* Old style negotiation header, no room for options
@@ -1826,7 +1826,9 @@ static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
          return -EIO;
      }
 
-    if (request->type == NBD_CMD_READ || request->type == NBD_CMD_WRITE) {
+    if (request->type == NBD_CMD_READ || request->type == NBD_CMD_WRITE ||
+        request->type == NBD_CMD_CACHE)
+    {
          if (request->len > NBD_MAX_BUFFER_SIZE) {
              error_setg(errp, "len (%" PRIu32" ) is larger than max len (%u)",
                         request->len, NBD_MAX_BUFFER_SIZE);
@@ -1911,7 +1913,7 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
      int ret;
      NBDExport *exp = client->exp;
 
-    assert(request->type == NBD_CMD_READ);
+    assert(request->type == NBD_CMD_READ || request->type == NBD_CMD_CACHE);
 
      /* XXX: NBD Protocol only documents use of FUA with WRITE */
      if (request->flags & NBD_CMD_FLAG_FUA) {

nbd/server.c static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request, · line 1938

Quoted 8 lines
nbd/server.c +1 -1
@@ -1930,7 +1932,7 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
 
      ret = blk_pread(exp->blk, request->from + exp->dev_offset, data,
                      request->len);
-    if (ret < 0) {
+    if (ret < 0 || request->type == NBD_CMD_CACHE) {
          return nbd_send_generic_reply(client, request->handle, ret,
                                        "reading from file failed", errp);
      }

ohh, forget the main thing:

nbd/server.c +0 -0
index 30d7d3f444..d6a161c8d5 100644
@@ -1965,6 +1965,7 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
 

     switch (request->type) {
     case NBD_CMD_READ:
+    case NBD_CMD_CACHE:
         return nbd_do_cmd_read(client, request, data, errp);

     case NBD_CMD_WRITE:

Signature · 2 lines
Best regards,
Vladimir
#2 lore raw
In reply to Vladimir Sementsov-Ogievskiy
Quoted 14 lines · Vladimir Sementsov-Ogievskiy

Handle nbd CACHE command. Just do read, without sending read data back. Cache mechanism should be done by exported node driver chain.

---
 include/block/nbd.h |  3 ++-
 nbd/server.c        | 10 ++++++----
 2 files changed, 8 insertions(+), 5 deletions(-)
include/block/nbd.h +0 -0
index fcdcd54502..b4793d0a29 100644

include/block/nbd.h typedef struct NBDExtent { · line 138

Quoted 4 lines
include/block/nbd.h +1 -0
@@ -135,6 +135,7 @@ typedef struct NBDExtent {
 #define NBD_FLAG_SEND_TRIM         (1 << 5) /* Send TRIM (discard) */
 #define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send WRITE_ZEROES */
 #define NBD_FLAG_SEND_DF           (1 << 7) /* Send DF (Do not Fragment) */
+#define NBD_FLAG_SEND_CACHE        (1 << 8) /* Send CACHE (prefetch) */

Hmm, this flag is not documented in the upstream NBD protocol yet; are we sure it matches the xNBD implementation? We'll want at least a documentation patch proposed for the NBD list before taking this.

Signature · 3 lines
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org
#3 lore raw
Quoted 10 lines · Eric Blake
Quoted 9 lines · Vladimir Sementsov-Ogievskiy

Handle nbd CACHE command. Just do read, without sending read data back. Cache mechanism should be done by exported node driver chain.

---
  include/block/nbd.h |  3 ++-
  nbd/server.c        | 10 ++++++----
  2 files changed, 8 insertions(+), 5 deletions(-)
Quoted 13 lines

include/block/nbd.h typedef struct NBDExtent { · line 138

Quoted 9 lines
include/block/nbd.h +1 -0
index fcdcd54502..b4793d0a29 100644
@@ -135,6 +135,7 @@ typedef struct NBDExtent {
  #define NBD_FLAG_SEND_TRIM         (1 << 5) /* Send TRIM (discard) */
  #define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send WRITE_ZEROES */
  #define NBD_FLAG_SEND_DF           (1 << 7) /* Send DF (Do not Fragment) */
+#define NBD_FLAG_SEND_CACHE        (1 << 8) /* Send CACHE (prefetch) */

Hmm, this flag is not documented in the upstream NBD protocol yet; are we sure it matches the xNBD implementation? We'll want at least a documentation patch proposed for the NBD list before taking this.

The discussion already on list:
https://lists.debian.org/nbd/2018/03/msg00040.html

Signature · 2 lines
Best regards,
Vladimir
#4 lore raw
Quoted 26 lines · Vladimir Sementsov-Ogievskiy
Quoted 10 lines · Eric Blake
Quoted 9 lines · Vladimir Sementsov-Ogievskiy

Handle nbd CACHE command. Just do read, without sending read data back. Cache mechanism should be done by exported node driver chain.

---
  include/block/nbd.h |  3 ++-
  nbd/server.c        | 10 ++++++----

  2 files changed, 8 insertions(+), 5 deletions(-)
Quoted 14 lines
Quoted 10 lines
include/block/nbd.h +0 -0
index fcdcd54502..b4793d0a29 100644
@@ -135,6 +135,7 @@ typedef struct NBDExtent {
   #define NBD_FLAG_SEND_TRIM         (1 << 5) /* Send TRIM (discard) */
   #define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send WRITE_ZEROES */
   #define NBD_FLAG_SEND_DF           (1 << 7) /* Send DF (Do not

Fragment) */
+#define NBD_FLAG_SEND_CACHE        (1 << 8) /* Send CACHE (prefetch) */

Hmm, this flag is not documented in the upstream NBD protocol yet; are we sure it matches the xNBD implementation?  We'll want at least a documentation patch proposed for the NBD list before taking this.

Quoted 2 lines

The discussion already on list:
https://lists.debian.org/nbd/2018/03/msg00040.html

Indeed, and that made me realize that we may want to add NBD_CMD_FLAG_* values corresponding to other useful posix_fadvise() modes before finalizing the NBD protocol addition of this feature, in which case we'd want to make sure the qemu implementation is in line with that.

Signature · 3 lines
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org
#5 lore raw
In reply to Vladimir Sementsov-Ogievskiy

Finally, what about this?

Quoted 72 lines · Vladimir Sementsov-Ogievskiy

Handle nbd CACHE command. Just do read, without sending read data back. Cache mechanism should be done by exported node driver chain.

---
  include/block/nbd.h |  3 ++-
  nbd/server.c        | 10 ++++++----
  2 files changed, 8 insertions(+), 5 deletions(-)
include/block/nbd.h +2 -1
index fcdcd54502..b4793d0a29 100644
@@ -135,6 +135,7 @@ typedef struct NBDExtent {
  #define NBD_FLAG_SEND_TRIM         (1 << 5) /* Send TRIM (discard) */
  #define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send WRITE_ZEROES */
  #define NBD_FLAG_SEND_DF           (1 << 7) /* Send DF (Do not Fragment) */
+#define NBD_FLAG_SEND_CACHE        (1 << 8) /* Send CACHE (prefetch) */
 
  /* New-style handshake (global) flags, sent from server to client, and
     control what will happen during handshake phase. */
@@ -195,7 +196,7 @@ enum {
      NBD_CMD_DISC = 2,
      NBD_CMD_FLUSH = 3,
      NBD_CMD_TRIM = 4,
-    /* 5 reserved for failed experiment NBD_CMD_CACHE */
+    NBD_CMD_CACHE = 5,
      NBD_CMD_WRITE_ZEROES = 6,
      NBD_CMD_BLOCK_STATUS = 7,
  };
nbd/server.c +6 -4
index 9e1f227178..30d7d3f444 100644
@@ -1134,7 +1134,7 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
      int ret;
      const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
                                NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA |
-                              NBD_FLAG_SEND_WRITE_ZEROES);
+                              NBD_FLAG_SEND_WRITE_ZEROES | NBD_FLAG_SEND_CACHE);
      bool oldStyle;
 
      /* Old style negotiation header, no room for options
@@ -1826,7 +1826,9 @@ static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
          return -EIO;
      }
 
-    if (request->type == NBD_CMD_READ || request->type == NBD_CMD_WRITE) {
+    if (request->type == NBD_CMD_READ || request->type == NBD_CMD_WRITE ||
+        request->type == NBD_CMD_CACHE)
+    {
          if (request->len > NBD_MAX_BUFFER_SIZE) {
              error_setg(errp, "len (%" PRIu32" ) is larger than max len (%u)",
                         request->len, NBD_MAX_BUFFER_SIZE);
@@ -1911,7 +1913,7 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
      int ret;
      NBDExport *exp = client->exp;
 
-    assert(request->type == NBD_CMD_READ);
+    assert(request->type == NBD_CMD_READ || request->type == NBD_CMD_CACHE);
 
      /* XXX: NBD Protocol only documents use of FUA with WRITE */
      if (request->flags & NBD_CMD_FLAG_FUA) {
@@ -1930,7 +1932,7 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
 
      ret = blk_pread(exp->blk, request->from + exp->dev_offset, data,
                      request->len);
-    if (ret < 0) {
+    if (ret < 0 || request->type == NBD_CMD_CACHE) {
          return nbd_send_generic_reply(client, request->handle, ret,
                                        "reading from file failed", errp);
      }
Signature · 2 lines
Best regards,
Vladimir
#6 lore raw
Quoted 5 lines · Vladimir Sementsov-Ogievskiy

Finally, what about this?

Quoted 2 lines · Vladimir Sementsov-Ogievskiy

Handle nbd CACHE command. Just do read, without sending read data back. Cache mechanism should be done by exported node driver chain.

Still waiting on the NBD spec review, which I've pinged on the NBD list. But as mentioned there, I'll probably go ahead and accept this (possibly with slight tweaks) on Monday, after giving one more weekend for any last-minute review comments.

Quoted 4 lines
Quoted 4 lines
nbd/server.c +0 -0
@@ -1826,7 +1826,9 @@ static int nbd_co_receive_request(NBDRequestData 
 *req, NBDRequest *request,
           return -EIO;
       }
Quoted 8 lines
Quoted 8 lines
(quoted diff) +1 -1
-    if (request->type == NBD_CMD_READ || request->type == 
 NBD_CMD_WRITE) {
+    if (request->type == NBD_CMD_READ || request->type == 

NBD_CMD_WRITE ||
+        request->type == NBD_CMD_CACHE)
+    {
          if (request->len > NBD_MAX_BUFFER_SIZE) { error_setg(errp, "len (%" PRIu32" ) is larger than max len (%u)",

I'm not sure I agree with this one. Since we aren't passing the cached data over the wire, we can reject the command with EINVAL instead of killing the connection entirely.

(As it is, I wonder if we can be nicer about rejecting a read request > 32M. For a write request, we have to disconnect; but for a read request, we can keep the connection alive by just returning EINVAL for a too-large read, instead of our current behavior of disconnecting)

Quoted 10 lines
Quoted 10 lines

                         request->len, NBD_MAX_BUFFER_SIZE);

nbd/server.c +1 -1
@@ -1911,7 +1913,7 @@ static coroutine_fn int 
 nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
       int ret;
       NBDExport *exp = client->exp;
-    assert(request->type == NBD_CMD_READ);
+    assert(request->type == NBD_CMD_READ || request->type == 
 NBD_CMD_CACHE);
       /* XXX: NBD Protocol only documents use of FUA with WRITE */
       if (request->flags & NBD_CMD_FLAG_FUA) {
Quoted 8 lines

nbd/server.c static coroutine_fn int · line 1937

Quoted 8 lines
nbd/server.c +1 -1
@@ -1930,7 +1932,7 @@ static coroutine_fn int 
 nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
       ret = blk_pread(exp->blk, request->from + exp->dev_offset, data,
                       request->len);
-    if (ret < 0) {
+    if (ret < 0 || request->type == NBD_CMD_CACHE) {
           return nbd_send_generic_reply(client, request->handle, ret,
                                         "reading from file failed", errp);

As for the implementation on the server side, yes, this looks reasonable, given the proposed spec wording being considered on the NBD list.

Signature · 3 lines
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org
#7 lore raw
Quoted 9 lines · Eric Blake
Quoted 5 lines · Vladimir Sementsov-Ogievskiy

Finally, what about this?

Quoted 2 lines · Vladimir Sementsov-Ogievskiy

Handle nbd CACHE command. Just do read, without sending read data back. Cache mechanism should be done by exported node driver chain.

Still waiting on the NBD spec review, which I've pinged on the NBD list. But as mentioned there, I'll probably go ahead and accept this (possibly with slight tweaks) on Monday, after giving one more weekend for any last-minute review comments.

Quoted 14 lines
Quoted 4 lines
Quoted 4 lines
nbd/server.c +0 -0
@@ -1826,7 +1826,9 @@ static int 
 nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
           return -EIO;
       }
Quoted 8 lines
Quoted 8 lines
(quoted diff) +1 -1
-    if (request->type == NBD_CMD_READ || request->type == 
 NBD_CMD_WRITE) {
+    if (request->type == NBD_CMD_READ || request->type == 

NBD_CMD_WRITE ||
+        request->type == NBD_CMD_CACHE)
+    {
          if (request->len > NBD_MAX_BUFFER_SIZE) { error_setg(errp, "len (%" PRIu32" ) is larger than max len (%u)",

I'm not sure I agree with this one. Since we aren't passing the cached data over the wire, we can reject the command with EINVAL instead of killing the connection entirely.

this chunk do entirely this: return EINVAL :)

Quoted 26 lines

(As it is, I wonder if we can be nicer about rejecting a read request

Quoted 1 line

32M. For a write request, we have to disconnect; but for a read

request, we can keep the connection alive by just returning EINVAL for a too-large read, instead of our current behavior of disconnecting)

Quoted 10 lines
Quoted 10 lines

request->len, NBD_MAX_BUFFER_SIZE);

nbd/server.c +1 -1
@@ -1911,7 +1913,7 @@ static coroutine_fn int 
 nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
       int ret;
       NBDExport *exp = client->exp;
-    assert(request->type == NBD_CMD_READ);
+    assert(request->type == NBD_CMD_READ || request->type == 
 NBD_CMD_CACHE);
       /* XXX: NBD Protocol only documents use of FUA with WRITE */
       if (request->flags & NBD_CMD_FLAG_FUA) {
Quoted 8 lines

nbd/server.c static coroutine_fn int · line 1937

Quoted 8 lines
nbd/server.c +1 -1
@@ -1930,7 +1932,7 @@ static coroutine_fn int 
 nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
       ret = blk_pread(exp->blk, request->from + exp->dev_offset, data,
                       request->len);
-    if (ret < 0) {
+    if (ret < 0 || request->type == NBD_CMD_CACHE) {
           return nbd_send_generic_reply(client, request->handle, ret,
                                         "reading from file failed", errp);

As for the implementation on the server side, yes, this looks reasonable, given the proposed spec wording being considered on the NBD list.

Signature · 2 lines
Best regards,
Vladimir
#8 lore raw
In reply to Eric Blake
Quoted 8 lines · Eric Blake
Quoted 5 lines · Vladimir Sementsov-Ogievskiy

Finally, what about this?

Quoted 2 lines · Vladimir Sementsov-Ogievskiy

Handle nbd CACHE command. Just do read, without sending read data back. Cache mechanism should be done by exported node driver chain.

Still waiting on the NBD spec review, which I've pinged on the NBD list. But as mentioned there, I'll probably go ahead and accept this (possibly with slight tweaks) on Monday, after giving one more weekend for any last-minute review comments.

Hmm, Eric?

Quoted 41 lines
Quoted 13 lines
Quoted 8 lines
(quoted diff) +1 -1
@@ -1826,7 +1826,9 @@ static int 
 nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
           return -EIO;
       }
-    if (request->type == NBD_CMD_READ || request->type == 
 NBD_CMD_WRITE) {
+    if (request->type == NBD_CMD_READ || request->type == 
Quoted 5 lines

NBD_CMD_WRITE ||
+        request->type == NBD_CMD_CACHE)
+    {
          if (request->len > NBD_MAX_BUFFER_SIZE) { error_setg(errp, "len (%" PRIu32" ) is larger than max len (%u)",

I'm not sure I agree with this one. Since we aren't passing the cached data over the wire, we can reject the command with EINVAL instead of killing the connection entirely.

(As it is, I wonder if we can be nicer about rejecting a read request

Quoted 1 line

32M. For a write request, we have to disconnect; but for a read

request, we can keep the connection alive by just returning EINVAL for a too-large read, instead of our current behavior of disconnecting)

Quoted 10 lines
Quoted 10 lines

request->len, NBD_MAX_BUFFER_SIZE);

nbd/server.c +1 -1
@@ -1911,7 +1913,7 @@ static coroutine_fn int 
 nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
       int ret;
       NBDExport *exp = client->exp;
-    assert(request->type == NBD_CMD_READ);
+    assert(request->type == NBD_CMD_READ || request->type == 
 NBD_CMD_CACHE);
       /* XXX: NBD Protocol only documents use of FUA with WRITE */
       if (request->flags & NBD_CMD_FLAG_FUA) {
Quoted 8 lines

nbd/server.c static coroutine_fn int · line 1937

Quoted 8 lines
nbd/server.c +1 -1
@@ -1930,7 +1932,7 @@ static coroutine_fn int 
 nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
       ret = blk_pread(exp->blk, request->from + exp->dev_offset, data,
                       request->len);
-    if (ret < 0) {
+    if (ret < 0 || request->type == NBD_CMD_CACHE) {
           return nbd_send_generic_reply(client, request->handle, ret,
                                         "reading from file failed", errp);

As for the implementation on the server side, yes, this looks reasonable, given the proposed spec wording being considered on the NBD list.

Signature · 2 lines
Best regards,
Vladimir
Reviewed-by on v1 1/1
#9 lore raw
In reply to Vladimir Sementsov-Ogievskiy
Quoted 8 lines · Vladimir Sementsov-Ogievskiy

Handle nbd CACHE command. Just do read, without sending read data back. Cache mechanism should be done by exported node driver chain.

---
  include/block/nbd.h |  3 ++-
  nbd/server.c        | 10 ++++++----
  2 files changed, 8 insertions(+), 5 deletions(-)

Missing a change to nbd/common.c nbd_cmd_lookup().

Review static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request, · line 1916

Quoted 6 lines
(quoted diff) +1 -1
@@ -1911,7 +1913,7 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
      int ret;
      NBDExport *exp = client->exp;
 
-    assert(request->type == NBD_CMD_READ);
+    assert(request->type == NBD_CMD_READ || request->type == NBD_CMD_CACHE);

Also, missing a call into this function for NBD_CMD_CACHE.

Squashing the following, then adding to my NBD queue, with:

nbd/common.c +2 -0
index 8c95c1d606e..41f5ed8d9fa 100644
@@ -148,6 +148,8 @@ const char *nbd_cmd_lookup(uint16_t cmd)
         return "flush";
     case NBD_CMD_TRIM:
         return "trim";
+    case NBD_CMD_CACHE:
+        return "cache";
     case NBD_CMD_WRITE_ZEROES:
         return "write zeroes";
     case NBD_CMD_BLOCK_STATUS:
nbd/server.c +1 -0
index 323c6d84004..274604609f4 100644
@@ -2173,6 +2173,7 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
 
     switch (request->type) {
     case NBD_CMD_READ:
+    case NBD_CMD_CACHE:
         return nbd_do_cmd_read(client, request, data, errp);
 
     case NBD_CMD_WRITE:
Signature · 3 lines
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org