This is an incomplete outline implementation for a libblkio plugin
for
nbdkit. At the moment it only supports reading the same ("capacity")
of the device, and not even reading or writing. I have some questions
about the libblkio API before I can complete the plugin (see below).
The idea here is that by connecting libblkio to NBD we can use the
existing set of scripting tools to script access to devices. For
example you could use Python to read or modify a device:
----------------------------------------------------------------------
$ nbdsh -c - <<'EOF'
from subprocess import *
# Run nbdkit-blkio-plugin.
h.connect_systemd_socket_activation ("nbdkit" "blkio",
"virtio-blk-vhost-user",
"path=unix.sock")
print("device size=%d", h.get_size())
# Dump the boot sector.
bootsect = h.pread(512, 0)
p = Popen("hexdump -C", shell=True, stdin=PIPE)
p.stdin.write(bootsect)
EOF
----------------------------------------------------------------------
So my questions and comments about libblkio:
(1) There is no way to know which properties are readable, writable,
and those which need to be set before or after blkio_connect (see
is_preconnect_property in the plugin). It should be possible to
introspect this information. Also might be nice to be able read a
list of all available properties.
(2) It would be nice if libblkio had a way to enable debugging and
call the caller back for debug messages. We could then redirect the
callbacks into the nbdkit debug API (nbdkit_debug()) where they would
eventually end up on stderr or syslog.
Thanks, I created a couple issues for these features.
However don't send debug messages to stderr, or at least allow
that
behaviour to be overridden.
(3) It seems like some drivers require pre-allocated memory regions,
and since some do that means we might as well implement this. It
also seems like some drivers require file-backed pre-allocated
memory regions, and so we might as well implement that too.
However what is not clear: does memfd_create(2) always allocate
sufficiently aligned memory regions, such that we never need to bother
reading the mem-region-alignment property?
mem-region-alignment is currently allowed to exceed the page size, but
I'm not sure if it ever could in practice. (Maybe it could due to
IOMMU alignment restrictions?)
I notice that the example:
https://gitlab.com/libblkio/libblkio/-/blob/main/examples/blkio-copy.c
just passes on this and calls blkio_alloc_mem_region(). Is that the
safest and easiest thing to do which will always work?
Yes.
(4) As a first pass, I only want to bother implementing blocking
mode.
It'll be slow, but it doesn't matter for this application. Also I've
chosen nbdkit's NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS so nbdkit
will serialise all requests (again, only for a very simple first pass).
Looking at:
https://libblkio.gitlab.io/libblkio/blkio.html#performing-i-o
seems simple enough but:
(4a) What is the queue number? Always 0? Is it affected by num-entries?
With n = num-queues, (non-poll) queues have indices 0 through n-1.
num-queues is 1 by default.
num-entries is the size of each of those queues for io_uring drivers,
and doesn't affect their index.
(4b) It's unclear how completions work. If I set min=max=1,
will it
return after the whole operation has completed? Do I need to
call it again? What about if the request is very large, can it
get split?
blkioq_do_io() will only return after at least min completions have
been copied out into the user's completion array. (Unless it fails, in
which case it returns an error and no completions are copied
out/consumed.)
With min=max=1, blkioq_do_io() will wait until at least one completion
is available, copy it out, and return 1. It will never return 0.
Requests are never split (by libblkio). If read/write requests are
larger than max-transfer, they fail.
Alberto