Libublk
Rust library for building linux ublk target device, which talks with
linux ublk driver^1 for exposing standard linux block device,
meantime all target IO logic is implemented in userspace.
Linux kernel 6.0 starts to support ublk covered by config option of CONFIG_BLK_DEV_UBLK.
Documentations
Quick Start
Follows one 2-queue ublk-null target which is built over libublk, ublk block device(/dev/ublkbN) is created after the code is run. And the device will be deleted after terminating this process by ctrl+C.
use ;
// async/.await IO handling
async
async
-
examples/loop.rs: real example using async/await & io_uring. -
examples/ramdisk.rs: single thread & async/.await for both ctrl and IO, this technique will be extended to create multiple devices from single thread in future
rublk^4 is based on libublk, and supports null, loop, zoned & qcow2 targets so
far.
unprivileged ublk support
In unprivileged mode(UBLK_F_UNPRIVILEGED_DEV), ublk device can be created
in non-admin user session. For supporting this feature:
- install udev rules
KERNEL=="ublk-control", MODE="0666", OPTIONS+="static_node=ublk-control"
ACTION=="add",KERNEL=="ublk[bc]*",RUN+="/usr/local/sbin/ublk_chown.sh %k 'add' '%M' '%m'"
ACTION=="remove",KERNEL=="ublk[bc]*",RUN+="/usr/local/sbin/ublk_chown.sh %k 'remove' '%M' '%m'"
- install utility and script
utils/ublk_chown.sh and binary of utils/ublk_user_id.rs needs to be
installed under /usr/local/sbin or other directory which has to match
with the udev rules.
Mount namespace caveat (container / Kubernetes pod)
The ublk daemon must not share a mount namespace with any process that
uses the ublk block device (mounts a filesystem on /dev/ublkbN,
opens it for I/O, etc.).
Reason: the ublk daemon serves I/O for /dev/ublkbN, so I/O on that
device only makes forward progress while the daemon is alive. When the
daemon shares a mount namespace with a client of its own device (e.g. a
filesystem mounted on /dev/ublkbN), the daemon's exit can trigger an
unmount that flushes I/O to the device — but the daemon is exiting and
can no longer serve that I/O, so it self-deadlocks.
Run the daemon in its own mount namespace, e.g. by calling
unshare(CLONE_NEWNS) at startup or launching it under unshare --mount.
See
vmtest/tests/ublk-mntns-min.sh
for a minimal reproducer of what goes wrong otherwise. Tracked at
libublk-rs#50.
Test
You can run the test of the library with cargo test
Performance
When running fio t/io_uring /dev/ublkb0^2, IOPS is basically same with
running same test over ublk device created by blktests miniublk^3, which
is written by pure C. And the ublk device is null, which has 2 queues, each
queue's depth is 64.
Example
loop
cargo run --example loop help
null
cargo run --example null help
License
This project is licensed under either of Apache License, Version 2.0 or MIT license at your option.
Contributing
Any kinds of contributions are welcome!