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 set .can_cache to false. Fortunately, when maxlen is larger than maxblock, and the plugin supports .cache, this results in a lot fewer calls into the plugin than the .pread fallback.
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 <[email protected]> --- filters/blocksize/blocksize.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/filters/blocksize/blocksize.c b/filters/blocksize/blocksize.c index 4f3e9a3..2d28222 100644 --- a/filters/blocksize/blocksize.c +++ b/filters/blocksize/blocksize.c @@ -1,5 +1,5 @@ /* nbdkit - * Copyright (C) 2018 Red Hat Inc. + * Copyright (C) 2018-2019 Red Hat Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -389,6 +389,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", @@ -404,6 +432,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 _______________________________________________ Libguestfs mailing list [email protected] https://www.redhat.com/mailman/listinfo/libguestfs
