DEV Community

Amarjargal
Amarjargal

Posted on

Testing ublk on Ubuntu 22.04

ublk is a generic framework for implementing block device logic in the userspace. It's developed by our mentor Ming Lei. Here is an article that described the workings and future possibilities of ublk. Reading all about its possibilities, I'm super excited to work with this project.

ublk is comprised of two parts: kernel ublk driver which is newly introduced to the Linux kernel since version 6.0 and userspace daemon (ublksrv).

When testing ublk driver on a Fedora 37 VM, it worked out of the box. But those who want to use it on Ubuntu, for now, will have to update their kernel to version 6.0 or up and configure it to enable ublk driver. I have Ubuntu 22.04 Jammmy Jellyfish and kernel 5.15. So the first step is to configure and build the kernel.

1. Configure and build the Linux kernel

Download the latest stable kernel from kernel.org. The latest kernel as of this writing was 6.1.4.

Extract it:

tar xvf linux-6.1.4.tar.xz 
Enter fullscreen mode Exit fullscreen mode

Go to the extracted directory and copy the current kernel's configuration:

cd linux-6.1.4 cp -v /boot/config-$(uname -r) .config 
Enter fullscreen mode Exit fullscreen mode

The new kernel will have many new config options. To keep the old configuration and also to configure the new options to their default values, run the following:

make olddefconfig 
Enter fullscreen mode Exit fullscreen mode

Configure ublk_drv by running the GUI menuconfig, navigating to Device drivers -> Block devices and add M to the Userspace block driver (Experimental) to make it a loadable module. Click Save and Exit.

make menuconfig 
Enter fullscreen mode Exit fullscreen mode

Image description

Disable the conflicting security certificates. Without disabling them, the make will fail with error. This might not be the best solution, but the easiest one and serves my purpose.

scripts/config --disable SYSTEM_TRUSTED_KEYS scripts/config --disable SYSTEM_REVOCATION_KEYS 
Enter fullscreen mode Exit fullscreen mode

Build and install. Use -j option to speed up the build process as it takes a lot of time. nproc will return the number of cores you can use.

make -j16 make modules sudo make modules_install sudo make install 
Enter fullscreen mode Exit fullscreen mode

Update grub bootloader:

sudo update-grub 
Enter fullscreen mode Exit fullscreen mode

Reboot

2. Build and install liburing

libiring is library for the new Linux asynchronous IO interface called io_uring. This is the interface ublk uses and will require version 2.2 or up.

You can install liburing with apt as shown below, but it was not the latest version.

sudo apt install liburing2 liburing-dev 
Enter fullscreen mode Exit fullscreen mode

Therefore, I just built it from the cloned source.

$ git clone https://github.com/axboe/liburing $ cd liburing $ ./configure $ make $ sudo make install 
Enter fullscreen mode Exit fullscreen mode

3. Build ubdsrv (userspace daemon)

git clone https://github.com/ming1/ubdsrv.git autoreconf -i ./configure make 
Enter fullscreen mode Exit fullscreen mode

4. Try ublk

First, load ublk_drv as a module. After it's loaded, a device called /dev/ublk_control is created. Userspace daemon will communicate with this device.

sudo modprobe ublk_drv 
Enter fullscreen mode Exit fullscreen mode

Then I tried ublk by following the Quick start tutorial on ubdsrv's source page. For now, ublk commands need root permission to run.

null disk

$ sudo ublk add -t null dev id 0: nr_hw_queues 1 queue_depth 128 block size 512 dev_capacity 524288000 max rq size 524288 daemon pid 235918 flags 0x2 state LIVE queue 0: tid 235919 affinity(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ) target {"dev_size":268435456000,"name":"null","type":0} 
Enter fullscreen mode Exit fullscreen mode

After the above command executed, ublk block device ublkb0 and a char device ublkc0 is added by the ublk driver in /dev/

$ ls /dev/ublk ublkb0 ublkc0 ublk-control 
Enter fullscreen mode Exit fullscreen mode

loop device

A raw disk image created with qemu-img is used.

$ qemu-img create -f raw foo.img 4G $ sudo ublk add -t loop -f foo.img [sudo] password for amar: ublk dev id 1: nr_hw_queues 1 queue_depth 128 block size 4096 dev_capacity 8388608 max rq size 524288 daemon pid 329999 flags 0x2 state LIVE queue 0: tid 330000 affinity(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ) target {"backing_file":"foo.img","dev_size":4294967296,"direct_io":1,"name":"loop","type":1} $ ls /dev/ublk ublkb0 ublkb1 ublkc0 ublkc1 ublk-control 
Enter fullscreen mode Exit fullscreen mode

You can format the block device /dev/ublkb1 with xfs, mount it and can do anything you want with it.

$ sudo mkfs.xfs /dev/ublkb0 meta-data=/dev/ublkb0 isize=512 agcount=4, agsize=262144 blks = sectsz=4096 attr=2, projid32bit=1 = crc=1 finobt=1, sparse=1, rmapbt=0 = reflink=1 bigtime=0 inobtcount=0 data = bsize=4096 blocks=1048576, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0, ftype=1 log =internal log bsize=4096 blocks=2560, version=2 = sectsz=4096 sunit=1 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 Discarding blocks...Done. $ sudo mount /dev/ublkb0 /mnt/tmp/ $ sudo mkdir /mnt/tmp/test $ ls /mnt/tmp/ test $ sudo umount /mnt/tmp 
Enter fullscreen mode Exit fullscreen mode

qcow2 disk

qcow2 support is still experimental, but I was able to add the Fedora disk image created in my previous blog post.

$ sudo ublk add -t qcow2 -f ../fedora/fedora37.qcow2 dev id 2: nr_hw_queues 1 queue_depth 128 block size 512 dev_capacity 62914560 max rq size 524288 daemon pid 243562 flags 0x2 state LIVE queue 0: tid 243564 affinity(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ) target {"backing_file":"../fedora/fedora37.qcow2","cluster_bits":16,"dev_size":32212254720,"header_length":112,"l1_size":60,"name":"qcow2","refcount_order":4,"refcount_table_clusters":1,"type":2,"version":3} 
Enter fullscreen mode Exit fullscreen mode

ublkb2p1, ublkb2p2 and ublkb2p3 are added for each partition of the disk. Then we can mount the main partition and access the filesystem.

$ ls /dev/ublk ublkb0 ublkb1 ublkb2 ublkb2p1 ublkb2p2 ublkb2p3 ublkc0 ublkc1 ublkc2 ublk-control $ sudo mount /dev/ublkb2p3 /mnt/tmp/ $ ls /mnt/tmp/ afs bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var $ sudo umount /mnt/tmp 
Enter fullscreen mode Exit fullscreen mode

List all the devices:

$ sudo ublk list dev id 0: nr_hw_queues 1 queue_depth 128 block size 512 dev_capacity 524288000 max rq size 524288 dae$ sudo umount /mnt/tmpmon pid 235918 flags 0x2 state LIVE queue 0: tid 235919 affinity(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ) target {"dev_size":268435456000,"name":"null","type":0} dev id 1: nr_hw_queues 1 queue_depth 128 block size 4096 dev_capacity 8388608 max rq size 524288 daemon pid 329999 flags 0x2 state LIVE queue 0: tid 330000 affinity(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ) target {"backing_file":"foo.img","dev_size":4294967296,"direct_io":1,"name":"loop","type":1} dev id 2: nr_hw_queues 1 queue_depth 128 block size 512 dev_capacity 62914560 max rq size 524288 daemon pid 243562 flags 0x2 state LIVE queue 0: tid 243564 affinity(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ) target {"backing_file":"../fedora/fedora37.qcow2","cluster_bits":16,"dev_size":32212254720,"header_length":112,"l1_size":60,"name":"qcow2","refcount_order":4,"refcount_table_clusters":1,"type":2,"version":3} 
Enter fullscreen mode Exit fullscreen mode

Remove all devices:

sudo ublk del -a 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)