Note
: I am not familiar with English. Please understand.
Preface
I've started to digging into ublk to replace NBD (Network Block Device).
Seems like it's fairly simple to implement using io_uring
to Queue requests and response.
Before to digging into that, I need a simple (but time-consuming task depends on your machine's horsepower) tasks: "Recompile WSL2 Kernel to support ublk"
the how-to
guides are derived from Microsoft's How-to use the Microsoft Linux kernel v6 on Windows Subsystem for Linux version 2 (WSL2) Documentation.
ublk is started to support Linux Kernel 6, so you should clone 6.0 version on WSL2 Kernel. Source
and there is a Release to add loadable modules, however it only supports NETFILTER_XT_TARGET_CT
, NETFILTER_XT_MATCH_BPF
, and NETFILTER_XT_MA
. I expects if they're release 6.x version of the Kernel, they'll supports more loadable kernel. (but you should've recompile the kernel for now)
the environment is based on Ubuntu (that the original documentation is based on Ubuntu (or Debian based OS that support apt
and other tools))
Build
0. Create Ubuntu Environment
- Enable WSL.
- Download Ubuntu from Microsoft Store.
1. Clone Microsoft's WSL2 Kernel Repository
the documentation suggest to clone whole repository's data (IDK why), but I'll takes some time depending on your Internet connectivity and machine's horsepower.
I'll add
depth
andbranch
when clone the repo to keep minimize.
$ git clone --depth=1 --branch linux-msft-wsl-6.1.y https://github.com/microsoft/WSL2-Linux-Kernel.git
2. Install dependencies.
- don't forget to install
bc
anddwarves
$ sudo apt update && sudo apt install build-essential flex bison libssl-dev libelf-dev bc dwarves
3. Modify config to enable CONFIG_BLK_DEV_UBLK
- Modify
Microsoft/config-wsl
to addCONFIG_BLK_DEV_UBLK=y
4. Compile!
the compile time can be slow depends on your machine's horsepower.
$ make -j$(nproc) KCONFIG_CONFIG=Microsoft/config-wsl
If the compile is success, you can see the line like this.
Kernel: arch/x86/boot/bzImage is ready (#2)
5. Install the kernel modules and headers
$ sudo make modules_install headers_install
6. Copy bzImage to Windows root drive
- replace
${USERNAME}
to appropriate Windows Username. - the
bzImage
is located onx86_64
directory. NOTx86
cp arch/x86_64/boot/bzImage /mnt/c/Users/${USERNAME}
7. Create wslconfig to use compiled kernel
- edit (or create)
%USERPROFILE%\.wslconfig
to use built kernel image. - usually,
%USERPROFILE%
is $HOME directory of Windows. (you can check via$env:USERPROFILE
)
[wsl2]
kernel=C:\\Users\${USERNAME}\bzImage
- and run
wsl --shutdown
to stop WSL instance as administrator.
8. Verify WSL is using compiled kernel.
- type
uname
to verify WSL instance is using compiled kernel.
$ uname -a # Linux ${USERNAME} 6.1.21.2-microsoft-standard-WSL2+ #2 SMP ${TIMESTAMP} x86_64 x86_64 x86_64 GNU/Linux
Build liburing2
liburing2 is not the latest version on Ubuntu. and ubdsrv requires liburing2
version greater than 2.2
, so It requires to build on myself.
Ref: https://dev.to/amarjargal/testing-ublk-on-ubuntu-2204-9pe
Clone Liburing
$ git clone https://github.com/axboe/liburing $ cd liburing $ git checkout liburing-2.5
Build Liburing
$ ./configure $ make $ sudo make install
Build Ubdsrv
- follow: https://github.com/ming1/ubdsrv#how-to-build-ublksrv
1. Clone Ubdsrv repository
$ git clone https://github.com/ming1/ubdsrv.git
2. Install dependencies
$ sudo apt install autoconf libtool pkg-config
3. Build and Install
$ autoreconf -i $ ./configure #pkg-config and libtool is usually needed $ sudo make install
4. Add Library Path to /etc/ld.so.conf
- when you run
ublk
, you'll get error like this.
$ ublk # ublk: error while loading shared libraries: libublksrv.so.0: cannot open shared object file: No such file or directory
-
you should modify
/etc/ld.so.conf
to add/usr/local/lib/
and runsudo ldconfig
to apply the configuration. -
when all of the configuration is correctly applied, you can see commands list when you type
ublk
$ ublk --help
ublk add -t {null|loop|qcow2|nbd}
-n DEV_ID -q NR_HW_QUEUES -d QUEUE_DEPTH
-u URING_COMP -g NEED_GET_DATA -r USER_RECOVERY
-i USER_RECOVERY_REISSUE --debug_mask=0x{DBG_MASK}
--unprivileged
target specific command line:
loop: -f backing_file [--buffered_io]
default is direct IO to backing file
qcow2: -f backing_file
nbd: --host=$HOST [--port=$PORT] | --unix=$UNIX_PATH
ublk del -n DEV_ID [-a | --all]
ublk list [-n DEV_ID]
ublk recover [-n DEV_ID]
ublk features
ublk -v [--version]
ublk -h [--help]
Finally
you can use ublk
command to configure disks (by communicating with /dev/ublk-control
)
let's create 10G
of the image and add that image to ublk.
Prepare image
- you can adjust
10G
to another size.
$ fallocate -l 10G hello.img
Add image to Ublk
when you run the command, the receiver is running on background to handle request on the fly. (you can verify it using ps
command.)
$ sudo ublk add -t loop -f hello.img
when it success, it'll print like this. you can find device by ublkb
field.
dev id 0: nr_hw_queues 1 queue_depth 128 block size 4096 dev_capacity 20971520
max rq size 524288 daemon pid 10427 flags 0x0 state LIVE
ublkc: 0:0 ublkb: 0:6 owner: 0:0
queue 0: tid 10428 affinity(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 )
target {"backing_file":"hello.img","dev_size":10737418240,"direct_io":1,"name":"loop","type":1}
also, you can list added devices using ublk list
command.
Format Disk and Let it mount!
format the disk using mkfs.ext4
and mount to somewhere
$ sudo mkfs.ext4 /dev/ublkb0 # prepare mountpoint and mount $ sudo mkdir -p /mnt/ublk-mountpoint $ sudo mount /dev/ublkb0 /mnt/ublk-mountpoint
Remove Device
use ublk del
command to remove device.
you should run ublk list
first to find device number located on ublkb
field. and use that number to remove the device.