Rely on .can_cache passthrough to imply that our .cache won't be
called unless the plugin also has .cache. [Technically, that won't
happen until a later patch flips the default in filters.c]. Round the
cache request out, to cache the same range as would otherwise be
passed to the plugin's .pread if we had instead manually set
.can_cache to NBDKIT_CACHE_EMULATE.
Oddly enough, a client can submit an unaligned request for just under
4G of caching where our rounding would overflow a 32-bit integer, so
our rounding has to use a 64-bit temporary.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
filters/blocksize/blocksize.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/filters/blocksize/blocksize.c b/filters/blocksize/blocksize.c
index ba5d9e7..0978887 100644
--- a/filters/blocksize/blocksize.c
+++ b/filters/blocksize/blocksize.c
@@ -368,6 +368,34 @@ blocksize_extents (struct nbdkit_next_ops *next_ops, void *nxdata,
flags, extents, err);
}
+static int
+blocksize_cache (struct nbdkit_next_ops *next_ops, void *nxdata,
+ void *handle, uint32_t count, uint64_t offs, uint32_t flags,
+ int *err)
+{
+ uint32_t limit;
+ uint64_t remaining = count; /* Rounding out could exceed 32 bits */
+
+ /* Unaligned head */
+ limit = offs & (minblock - 1);
+ remaining += limit;
+ offs -= limit;
+
+ /* Unaligned tail */
+ remaining = ROUND_UP (remaining, minblock);
+
+ /* Aligned body */
+ while (remaining) {
+ limit = MIN (maxdata, remaining);
+ if (next_ops->cache (nxdata, limit, offs, flags, err) == -1)
+ return -1;
+ offs += limit;
+ remaining -= limit;
+ }
+
+ return 0;
+}
+
static struct nbdkit_filter filter = {
.name = "blocksize",
.longname = "nbdkit blocksize filter",
@@ -382,6 +410,7 @@ static struct nbdkit_filter filter = {
.trim = blocksize_trim,
.zero = blocksize_zero,
.extents = blocksize_extents,
+ .cache = blocksize_cache,
};
NBDKIT_REGISTER_FILTER(filter)
--
2.20.1