Although it is less common for a plugin to change its mind on whether
FUA or fast zeroes are supported, the backend will assert if the
original connection advertised support to the client, but a retry
causes the client's request with a flag to pass to a reopened plugin
without support.
For FUA, act the same as can_write and similar failures, forcing a
retry to see if the support appears yet again (and not trying to
fallback to a direct flush call).
For fast zero, fail fast without any retry.
As with other retry fixes, the test will be in the next patch.
Fixes: f0f0ec49
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
filters/retry/retry.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/filters/retry/retry.c b/filters/retry/retry.c
index ad31552c..840d7383 100644
--- a/filters/retry/retry.c
+++ b/filters/retry/retry.c
@@ -230,6 +230,11 @@ retry_pwrite (struct nbdkit_next_ops *next_ops, void *nxdata,
*err = EROFS;
r = -1;
}
+ else if (flags & NBDKIT_FLAG_FUA &&
+ next_ops->can_fua (nxdata) <= NBDKIT_FUA_NONE) {
+ *err = EIO;
+ r = -1;
+ }
else
r = next_ops->pwrite (nxdata, buf, count, offset, flags, err);
if (r == -1 && do_retry (h, &data, next_ops, nxdata, err)) goto again;
@@ -257,6 +262,11 @@ retry_trim (struct nbdkit_next_ops *next_ops, void *nxdata,
*err = EROFS;
r = -1;
}
+ else if (flags & NBDKIT_FLAG_FUA &&
+ next_ops->can_fua (nxdata) <= NBDKIT_FUA_NONE) {
+ *err = EIO;
+ r = -1;
+ }
else
r = next_ops->trim (nxdata, count, offset, flags, err);
if (r == -1 && do_retry (h, &data, next_ops, nxdata, err)) goto again;
@@ -302,10 +312,20 @@ retry_zero (struct nbdkit_next_ops *next_ops, void *nxdata,
*err = EROFS;
return -1;
}
+ if (flags & NBDKIT_FLAG_FAST_ZERO &&
+ next_ops->can_fast_zero (nxdata) != 1) {
+ *err = EOPNOTSUPP;
+ return -1;
+ }
if (next_ops->can_zero (nxdata) <= NBDKIT_ZERO_NONE) {
*err = EROFS;
r = -1;
}
+ else if (flags & NBDKIT_FLAG_FUA &&
+ next_ops->can_fua (nxdata) <= NBDKIT_FUA_NONE) {
+ *err = EIO;
+ r = -1;
+ }
else
r = next_ops->zero (nxdata, count, offset, flags, err);
if (r == -1 && do_retry (h, &data, next_ops, nxdata, err)) goto again;
--
2.21.0