If the target server supports FUA, then we should pass the client
flag through rather than emulating things with a less-efficient
flush.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
plugins/nbd/nbd.c | 35 +++++++++++++++++++++++++----------
1 file changed, 25 insertions(+), 10 deletions(-)
diff --git a/plugins/nbd/nbd.c b/plugins/nbd/nbd.c
index c9727f7..09cefe5 100644
--- a/plugins/nbd/nbd.c
+++ b/plugins/nbd/nbd.c
@@ -616,6 +616,14 @@ nbd_can_trim (void *handle)
return h->flags & NBD_FLAG_SEND_TRIM;
}
+static int
+nbd_can_fua (void *handle)
+{
+ struct handle *h = handle;
+
+ return h->flags & NBD_FLAG_SEND_FUA;
+}
+
/* Read data from the file. */
static int
nbd_pread (void *handle, void *buf, uint32_t count, uint64_t offset)
@@ -631,23 +639,26 @@ nbd_pread (void *handle, void *buf, uint32_t count, uint64_t
offset)
/* Write data to the file. */
static int
-nbd_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset)
+nbd_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset,
+ int fua)
{
struct handle *h = handle;
int c;
/* TODO Auto-fragment this if the client has a larger max transfer
limit than the server */
- c = nbd_request_full (h, 0, NBD_CMD_WRITE, offset, count, buf, NULL);
+ c = nbd_request_full (h, fua ? NBD_CMD_FLAG_FUA : 0,
+ NBD_CMD_WRITE, offset, count, buf, NULL);
return c < 0 ? c : nbd_reply (h, c);
}
/* Write zeroes to the file. */
static int
-nbd_zero (void *handle, uint32_t count, uint64_t offset, int may_trim)
+nbd_zero (void *handle, uint32_t count, uint64_t offset, int may_trim, int fua)
{
struct handle *h = handle;
int c;
+ int flags = 0;
if (!(h->flags & NBD_FLAG_SEND_WRITE_ZEROES)) {
/* Trigger a fall back to regular writing */
@@ -655,19 +666,22 @@ nbd_zero (void *handle, uint32_t count, uint64_t offset, int
may_trim)
return -1;
}
- c = nbd_request (h, may_trim ? 0 : NBD_CMD_FLAG_NO_HOLE,
- NBD_CMD_WRITE_ZEROES, offset, count);
+ if (!may_trim)
+ flags |= NBD_CMD_FLAG_NO_HOLE;
+ if (fua)
+ flags |= NBD_CMD_FLAG_FUA;
+ c = nbd_request (h, flags, NBD_CMD_WRITE_ZEROES, offset, count);
return c < 0 ? c : nbd_reply (h, c);
}
/* Trim a portion of the file. */
static int
-nbd_trim (void *handle, uint32_t count, uint64_t offset)
+nbd_trim (void *handle, uint32_t count, uint64_t offset, int fua)
{
struct handle *h = handle;
int c;
- c = nbd_request (h, 0, NBD_CMD_TRIM, offset, count);
+ c = nbd_request (h, fua ? NBD_CMD_FLAG_FUA : 0, NBD_CMD_TRIM, offset, count);
return c < 0 ? c : nbd_reply (h, c);
}
@@ -697,11 +711,12 @@ static struct nbdkit_plugin plugin = {
.can_flush = nbd_can_flush,
.is_rotational = nbd_is_rotational,
.can_trim = nbd_can_trim,
+ .can_fua = nbd_can_fua,
.pread = nbd_pread,
- .pwrite = nbd_pwrite,
- .zero = nbd_zero,
+ .pwrite_fua = nbd_pwrite,
+ .zero_fua = nbd_zero,
.flush = nbd_flush,
- .trim = nbd_trim,
+ .trim_fua = nbd_trim,
.errno_is_preserved = 1,
};
--
2.14.3