This patch isn't complete (patch 6/6 isn't finished) so it's just for discussion, although it does compile and run. This introduces to nbdkit a concept of "filters" which can be placed in front of plugins to modify their behaviour. Some examples where you might use filters: * Serve a subset of the data, such as (offset, range) or a single partition from a disk image. * Inject delays or errors for testing clients. * Implement "copy-on-write" (a feature found in other NBD servers). Filters are implemented by allowing them to intercept methods before a plugin gets them. For example to implement a read delay the filter would register for a .pread hook which is implemented like this: static int delay_pread (void *handle, void *buf, uint32_t count, uint64_t offset, int (*next) (void *data, void *buf, uint32_t count, uint64_t offset), void *data) { nanosleep (...); return next (data, buf, count, offset); // calls next filter or plugin } ... static struct nbdkit_filter filter = { ... .pread = delay_pread, ... }; For the filters I want to write this works fine, but with two caveats: (1) If new datapath methods are introduced then filters won't get to see them by default. For example, if we modify offsets when calling .pread and .pwrite, and then later the .zero method is added to plugins, then existing filters won't modify the parameters of .zero correctly (resulting in wrong data being zeroed). (2) You cannot do anything more complex in one of these functions than calling the single underlying plugin method, possibly modifying the arguments. For example it's hard to see how a "qcow2 decoder" filter could be written since it would need to have full access to the plugin methods, not just to the single method. Unfortunately solving (1) & (2) makes the whole thing a lot more complicated. Rich.