imageio flush feature is compatible with NBC_CMD_FLAG_FUA. With flush=y,
write or zero will issue NBD_CMD_FLUSH at the end, so the call returns
only after the data is flush to storage.
The plugin reports now that it supports FUA (based on can_flush), and
when FUA flag is set, we translate it to flush query (PUT) or flag
(PATCH).
For example, this nbd command:
NBD_CMD_WRITE flags=NBD_CMD_FUA_FLAG
Is translated to this http request:
PUT /path?flush=y
On imageio server, this translates back to:
NBD_CMD_WRITE flags=0
NBD_CMD_FLUSH
Future version of imageio[1] may improve this by translating back to
single command:
NBD_CMD_WRITE flags=NBD_CMD_FUA_FLAG
qemu-img is not using FUA during conversion, but a future version may
use this feature.
[1]
https://bugzilla.redhat.com/1919548
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
v2v/rhv-upload-plugin.py | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py
index 0f8101dd..1c6f0603 100644
--- a/v2v/rhv-upload-plugin.py
+++ b/v2v/rhv-upload-plugin.py
@@ -161,6 +161,12 @@ def can_flush(h):
return h['can_flush']
+@failing
+def can_fua(h):
+ # imageio flush feature is is compatible with NBD_CMD_FLAG_FUA.
+ return h['can_flush']
+
+
@failing
def get_size(h):
return params['disk_size']
@@ -231,7 +237,9 @@ def pwrite(h, buf, offset, flags):
count = len(buf)
- http.putrequest("PUT", h['path'] + "?flush=n")
+ flush = "y" if (h['can_flush'] and (flags & nbdkit.FLAG_FUA))
else "n"
+
+ http.putrequest("PUT", h['path'] + "?flush=" + flush)
# The oVirt server only uses the first part of the range, and the
# content-length.
http.putheader("Content-Range", "bytes %d-%d/*" % (offset, offset
+ count - 1))
@@ -260,14 +268,16 @@ def zero(h, count, offset, flags):
# so nbdkit could call this even if the server doesn't support
# zeroing. If this is the case we must emulate.
if not h['can_zero']:
- emulate_zero(h, count, offset)
+ emulate_zero(h, count, offset, flags)
return
+ flush = bool(h['can_flush'] and (flags & nbdkit.FLAG_FUA))
+
# Construct the JSON request for zeroing.
buf = json.dumps({'op': "zero",
'offset': offset,
'size': count,
- 'flush': False}).encode()
+ 'flush': flush}).encode()
headers = {"Content-Type": "application/json",
"Content-Length": str(len(buf))}
@@ -283,10 +293,12 @@ def zero(h, count, offset, flags):
r.read()
-def emulate_zero(h, count, offset):
+def emulate_zero(h, count, offset, flags):
http = h['http']
- http.putrequest("PUT", h['path'])
+ flush = "y" if (h['can_flush'] and (flags & nbdkit.FLAG_FUA))
else "n"
+
+ http.putrequest("PUT", h['path'] + "?flush=" + flush)
http.putheader("Content-Range",
"bytes %d-%d/*" % (offset, offset + count - 1))
http.putheader("Content-Length", str(count))
--
2.26.2