2 ======================================================================
4 General ideas for improvements
5 ------------------------------
7 * Listen on specific interfaces or protocols.
9 * Performance - measure and improve it. Chart it over various buffer
10 sizes and threads, as that should make it easier to identify
13 * For parallel plugins, only create threads on demand from parallel
14 client requests, rather than pre-creating all threads at connection
15 time, up to the thread pool size limit. Of course, once created, a
16 thread is reused as possible until the connection closes.
18 * A new threading model, SERIALIZE_RETIREMENT, which lets the client
19 queue up multiple requests and processes them in parallel in the
20 plugin, but where the responses sent back to the client are in the
21 same order as the client's request rather than the plugin's
22 completion. This is stricter than fully parallel, but looser than
23 SERIALIZE_REQUESTS (in particular, a client can get
24 non-deterministic behavior if batched requests touch the same area
27 * Async callbacks. The current parallel support requires one thread
28 per pending message; a solution with fewer threads would split
29 low-level code between request and response, where the callback has
30 to inform nbdkit when the response is ready:
31 https://www.redhat.com/archives/libguestfs/2018-January/msg00149.html
33 * More NBD protocol features. The currently missing features are
34 structured replies for sparse reads, and online resize.
36 * Test that zero-length read/write/extents requests behave sanely
37 (NBD protocol says they are unspecified).
39 * If a client negotiates structured replies, and issues a read/extents
40 call that exceeds EOF (qemu 3.1 is one such client, when nbdkit
41 serves non-sector-aligned images), return the valid answer for the
42 subset of the request in range and then NBD_REPLY_TYPE_ERROR_OFFSET
43 for the tail, rather than erroring the entire request.
45 * Audit the code base to get rid of strerror() usage (the function is
46 not thread-safe); however, using geterror_r() can be tricky as it
47 has a different signature in glibc than in POSIX.
49 * Teach nbdkit_error() to have smart newline appending (for existing
50 inconsistent clients), while fixing internal uses to omit the
51 newline. Commit ef4f72ef has some ideas on smart newlines, but that
52 should probably be factored into a utility function.
54 * Add a mode of operation where nbdkit is handed a pre-opened fd to be
55 used immediately in transmission phase (skipping handshake). There
56 are already third-party clients of the kernel's /dev/nbdX which rely
57 on their own protocol instead of NBD handshake, before calling
58 ioctl(NBD_SET_SOCK); this mode would let the third-party client
59 continue to keep their non-standard handshake while utilizing nbdkit
60 to prototype new behaviors in serving the kernel.
62 * "nbdkit.so": nbdkit as a loadable shared library. The aim of nbdkit
63 is to make it reusable from other programs (see nbdkit-captive(1)).
64 If it was a loadable shared library it would be even more reusable.
65 API would allow you to create an nbdkit instance, configure it (same
66 as the current command line), start it serving on a socket, etc.
67 However perhaps the current ability to work well as a subprocess is
68 good enough? Also allowing multiple instances of nbdkit to be
69 loaded in the same process is probably impossible.
71 * Examine other fuzzers: https://gitlab.com/akihe/radamsa
73 * common/utils/vector.h could be extended and used in other places:
74 - there are some more possible places in the server (anywhere using
76 - add more iterators, map function, etc, as required.
78 * password=- to mean read a password interactively from /dev/tty (not
81 Suggestions for plugins
82 -----------------------
84 Note: qemu supports other formats such as libnfs, iscsi, gluster and
85 ceph/rbd, and while similar plugins could be written for nbdkit there
86 is no compelling reason unless the result is better than qemu-nbd.
87 For the majority of users it would be better if they were directed to
88 qemu-nbd for these use cases.
92 https://lists.gnu.org/archive/html/qemu-devel/2017-11/msg02971.html
93 is a partial solution but it needs cleaning up.
97 * Add boot sector support. In theory this is easy (eg. using
98 SYSLINUX), but the practical reality of making a fully bootable
99 floppy is rather more complex.
101 * Add multiple dir merging.
103 nbdkit-linuxdisk-plugin:
105 * Add multiple dir merging (in e2fsprogs mke2fs).
109 * Map export name to file parameter, allowing clients to access
110 multiple disks from a single VM.
112 * For testing VDDK, try to come up with delay filter + sparse plugin
113 settings which behave closely (in terms of performance and API
114 latency) to the real thing. This would allow us to tune some
115 performance tools without needing VMware all the time.
117 nbdkit-torrent-plugin:
119 * There are lots of settings we could map into parameters:
120 https://www.libtorrent.org/reference-Settings.html#settings_pack
122 * The C++ could be a lot more natural. At the moment it's a kind of
123 “C with C++ extensions”.
125 nbdkit-ondemand-plugin:
127 * Implement more callbacks, eg. .zero
129 * Allow client to select size up to a limit, eg. by sending export
130 names like ‘export:4G’.
134 * Allow expressions to evaluate to numbers, offsets, etc so that this
137 nbdkit data '(0x55 0xAA)*n' n=1000
139 * Allow inclusion of files where the file is not binary but is written
142 * Like $VAR but the variable is either binary or base64.
146 * Look at using skopeo instead of podman pull
147 (https://github.com/containers/skopeo)
151 * Use event-driven mode instead of blocking mode. This involves
152 restructuring the plugin so that there is one or more background
153 threads to handle the events, and nbdkit threads issue requests to
154 these threads. (See how it is done in the VDDK plugin.)
156 Suggestions for language plugins
157 --------------------------------
161 * Get the __docstring__ from the module and print it in --help output.
162 This requires changes to the core API so that config_help is a
163 function rather than a variable (see V3 suggestions below).
165 Suggestions for filters
166 -----------------------
168 * Add shared filter. Take advantage of filter context APIs to open a
169 single context into the backend shared among multiple client
170 connections. This may even allow a filter to offer a more parallel
171 threading model than the underlying plugin.
173 * CBT filter to track dirty blocks. See these links for inspiration:
174 https://www.cloudandheat.com/block-level-data-tracking-using-davice-mappers-dm-era/
175 https://github.com/qemu/qemu/blob/master/docs/interop/bitmaps.rst
177 * masking plugin features for testing clients (see 'nozero' and 'fua'
178 filters for examples)
180 * "bandwidth quota" filter which would close a connection after it
181 exceeded a certain amount of bandwidth up or down.
183 * "forward-only" filter. This would turn random access requests from
184 the client into serial requests in the plugin, meaning that the
185 plugin could be written to assume that requests only happen from
186 beginning to end. This is would be useful for plugins that have to
187 deal with non-seekable compressed data. Note the filter would have
188 to work by caching already-read data in a temporary file.
190 * nbdkit-cache-filter should handle ENOSPC errors automatically by
191 reclaiming blocks from the cache
193 * nbdkit-cache-filter could use a background thread for reclaiming.
195 * zstd filter was requested as a way to do what we currently do with
196 xz but saving many hours on compression (at the cost of hundreds of
198 https://github.com/facebook/zstd/issues/395#issuecomment-535875379
200 * nbdkit-exitlast-filter could probably use a configurable timeout so
201 that there is a grace period in case another connection comes along.
203 * nbdkit-pause-filter would probably be more useful if the filter
204 could inject a flush after pausing. However this requires that
205 filter background threads have access to the plugin (see above).
209 * This filter should also support LUKSv2 (and so should qemu).
211 * There are some missing features: ESSIV, more ciphers.
213 * Implement trim and zero if possible.
215 nbdkit-readahead-filter:
217 * The filter should open a new connection to the plugin per background
218 thread so it is able to work with plugins that use the
219 serialize_requests thread model (like curl). At the moment it makes
220 requests on the same connection, so it requires plugins to use the
221 parallel thread model.
223 * It should combine (or avoid) overlapping cache requests.
227 * allow other kinds of traffic shaping such as VBR
229 * limit traffic per client (ie. per IP address)
231 * split large requests to avoid long, lumpy sleeps when request size
232 is much larger than rate limit
236 * allow user to specify which errors cause a retry and which ones are
237 passed through; for example there's probably no point retrying on
240 * there are all kinds of extra complications possible here,
241 eg. specifying a pattern of retrying and reopening:
242 retry-method=RRRORRRRRORRRRR meaning to retry the data command 3
243 times, reopen, retry 5 times, etc.
249 * permit hostnames and hostname wildcards to be used in the
252 * the allow and deny lists should be updatable while nbdkit is
253 running, for example by storing them in a database file
255 nbdkit-extentlist-filter:
257 * read the extents generated by qemu-img map, allowing extents to be
258 ported from a qemu block device
260 * make non-read-only access safe by updating the extent list when the
261 filter sees writes and trims
263 nbdkit-exportname-filter:
265 * find a way to call the plugin's .list_exports during .open, so that
266 we can enforce exportname-strict=true without command line redundancy
268 * add a mode for passing in a file containing exportnames in the same
269 manner accepted by the sh/eval plugins, rather than one name (and no
270 description) per config parameter
275 Things like filtering by IP address can be done using external
276 wrappers (TCP wrappers, systemd), or nbdkit-ip-filter.
278 However it might be nice to have a configurable filter for preventing
279 valid but not sensible requests. The server already filters invalid
280 requests. This would be like seccomp, and could be implemented using
281 an eBPF-based parser. Unfortunately actual eBPF is difficult to use
282 for userspace processes. The "standard" isn't solidly defined - the
283 Linux kernel implementation is the standard - and Linux has by far the
284 best implementation, particularly around bytecode verification and
285 JITting. There is a userspace VM (ubpf) but it has very limited
286 capabilities compared to Linux.
291 Filters allow certain types of composition, but others would not be
292 possible, for example RAIDing over multiple nbd sources. Because the
293 plugin API limits us to loading a single plugin to the server, the
294 best way to do this (and the most robust) is to compose multiple
295 nbdkit processes. Perhaps libnbd will prove useful for this purpose.
300 * Figure out how to get 'make distcheck' working. VPATH builds are
301 working, but various pkg-config results that try to stick
302 bash-completion and ocaml add-ons into their system-wide home do
303 not play nicely with --prefix builds for a non-root user.
305 * Right now, 'make check' builds keys with an expiration of 1 year
306 only if they don't exist, and we leave the keys around except under
307 'make distclean'. This leads to testsuite failures when
308 (re-)building in an incremental tree first started more than a year
309 ago. Better would be having make unconditionally run the generator
310 scripts, but tweak the scripts themselves to be a no-op unless the
311 keys don't exist or have expired.
316 Currently many features are missing, including:
318 * Daemonization. This is not really applicable for Windows where you
319 would instead want to run nbdkit as a service using something like
320 SRVANY. You must use the -f option or one of the other options that
323 * These options are all unimplemented:
324 --exit-with-parent, --group, --run, --selinux-label, --single, --swap,
327 * Many other plugins and filters.
329 * errno_is_preserved should use GetLastError and/or WSAGetLastError
330 but currently does neither so errors from plugins are probably wrong
333 * Most tests are skipped because of the missing features above.
338 From time to time we may update the plugin protocol. This section
339 collects ideas for things which might be fixed in the next version of
342 Note that we keep the old protocol(s) around so that source
343 compatibility is retained. Plugins must opt in to the new protocol
344 using ‘#define NBDKIT_API_VERSION <version>’.
346 * All methods taking a ‘count’ field should be uint64_t (instead of
347 uint32_t). Although the NBD protocol does not support 64 bit
348 lengths, it might do in future.
350 * v2 .can_zero is tri-state for filters, but bool for plugins; in v3,
351 even plugins should get a say on whether to emulate
353 * v2 .can_extents is bool, and cannot affect our response to
354 NBD_OPT_SET_META_CONTEXT (that is, we are blindly emulating extent
355 support regardless of the export name). In v3, .can_extents should
356 be tri-state, with an explicit way to disable that context on a
359 * pread could be changed to allow it to support Structured Replies
360 (SRs). This could mean allowing it to return partial data, holes,
361 zeroes, etc. For a client that negotiates SR coupled with a plugin
362 that supports .extents, the v2 protocol would allow us to at least
363 synthesize NBD_REPLY_TYPE_OFFSET_HOLE for less network traffic, even
364 though the plugin will still have to fully populate the .pread
365 buffer; the v3 protocol should make sparse reads more direct.
367 * Parameters should be systematized so that they aren't just (key,
368 value) strings. nbdkit should know the possible keys for the plugin
369 and filters, and the type of the values, and both check and parse
372 * Modify open() API so it takes an export name and tls parameter.
374 * Modify get_ready() API to pass final selected thread model. Filters
375 already get this information, but to date, we have not yet seen a
376 reason to add nbdkit_get_thread_model for use by v2 plugins.
378 * Change config_help from a variable to a function.
380 * Consider extra parameters to .block_size(). First so that we can
381 separately control maximum data request (eg. pread) vs maximum
382 virtual request (eg. zero). Note that the NBD protocol does not yet
383 support this distinction. We may also need a 'bool strict'
384 parameter to specify whether the client requested block size
385 information or not. qemu-nbd can distinguish these two cases.
387 * Renumber thread models. Redefine existing thread models like this:
389 model existing value new value
390 SERIALIZE_CONNECTIONS 0 1000
391 SERIALIZE_ALL_REQUESTS 1 2000
392 SERIALIZE_REQUESTS 2 3000
395 This allows new thread models to be inserted before and between the
396 existing ones. In particular SERIALIZE_RETIREMENT has been
397 suggested above (inserted between SERIALIZE_REQUESTS and PARALLEL).
398 We could also imagine a thread model more like the one VDDK really
399 wants which calls open and close from the main thread.
401 For backwards compatibility the old numbers 0-3 can be transparently
402 mapped to the new values.