filters: Cache and change semantics of can_zero
commitfd3615548bd8d5f4662ac73ea2de66f2bb078202
authorEric Blake <eblake@redhat.com>
Tue, 3 Sep 2019 00:12:20 +0000 (2 19:12 -0500)
committerEric Blake <eblake@redhat.com>
Tue, 3 Sep 2019 01:30:57 +0000 (2 20:30 -0500)
tree8b33e9f8a75f75cd2cd06c4e2d5abab892848d59
parent14eb056c6298336aafdb7362b74cd19f158ac8ac
filters: Cache and change semantics of can_zero

The tri-state return pattern has proved valuable in other cases where
a backend wants to opt in or out of nbdkit fallbacks.  Using a
tri-state return pattern at the backend level unifies the different
semantics between plugin and filter .can_zero return values, and makes
it possible for plugins to use cached results of .can_zero rather than
calling into the plugin on each .zero request.  As in other recent
patches, it is easy to write an sh script that demonstrates a
resulting speedup from the caching.  All filters are in-tree and do
not have a promise of API compatability, so it's easy to update all of
them (the log filter is okay as-is, the nozero filter is easy to
update, and no other filter overrides .can_zero).  But for backwards
compatibility reasons, we cannot change the semantics of the plugin's
return value for .can_zero while remaining at API version 2; so that
remains a bool, and merely selects between EMULATE or NATIVE at the
backend level.

$ cat script
case "$1" in
    get_size) echo 1m;;
    can_zero) sleep 1;;
    can_write | zero) ;;
    *) exit 2 ;;
esac

Pre-patch:
$ /bin/time -f %e ./nbdkit -U - sh script \
  --run 'qemu-io -f raw -c "w -z 0 512" -c "w -z 512 512" $uri >/dev/null'
3.10

Post-patch:
$ /bin/time -f %e ./nbdkit -U - sh script \
  --run 'qemu-io -f raw -c "w -z 0 512" -c "w -z 512 512" $uri >/dev/null'
1.08

Signed-off-by: Eric Blake <eblake@redhat.com>
docs/nbdkit-filter.pod
filters/nozero/nozero.c
include/nbdkit-filter.h
server/backend.c
server/internal.h
server/plugins.c
server/protocol-handshake.c