Zoned Block Device Emulation with nullblk
Linux® null_blk driver is a powerful tool to emulate various types of block devices for tests. Since kernel 4.19, the null_blk driver gain the ability to emulate zoned block devices. With the addition of memory backup for data read and writen to a null_blk device, this driver provides an easy to use but yet powerful tool for application development and tests.
Creating a Zoned null Block Device
The simplest method to create a null_blk emulated zoned block device is to
specify the zoned=1
argument to null_blk modrpobe command line.
# modprobe null_blk nr_devices=1 zoned=1
This creates a single host managed zoned block device with a zone size of 256M and a total capacity of 250 GB (1000 zones). No conventional zones are created with this simple command.
# zbc_report_zones /dev/nullb0
Device /dev/nullb0:
Vendor ID: Unknown
Zoned block device interface, Host-managed zone model
524288000 512-bytes sectors
524288000 logical blocks of 512 B
524288000 physical blocks of 512 B
268.435 GB capacity
Read commands are unrestricted
127 KiB max R/W size
Maximum number of open sequential write required zones: 128
1000 zones from 0, reporting option 0x00
1000 / 1000 zones:
Zone 00000: type 0x2 (Sequential-write-required), cond 0x1 (Empty), reset recommended 0, non_seq 0, sector 0, 524288 sectors, wp 0
Zone 00001: type 0x2 (Sequential-write-required), cond 0x1 (Empty), reset recommended 0, non_seq 0, sector 524288, 524288 sectors, wp 524288
...
Zone 00998: type 0x2 (Sequential-write-required), cond 0x1 (Empty), reset recommended 0, non_seq 0, sector 523239424, 524288 sectors, wp 523239424
Zone 00999: type 0x2 (Sequential-write-required), cond 0x1 (Empty), reset recommended 0, non_seq 0, sector 523763712, 524288 sectors, wp 523763712
null_blk Zoned Block Device Parameters
The configfs interface of the null_blk driver provides a more powerful method for creating zoned null_blk devices. The configfs of the null_blk driver can be listed with the following command.
# cat /sys/kernel/config/nullb/features
memory_backed,discard,bandwidth,cache,badblocks,zoned,zone_size,zone_nr_conv
The parameters related to the zoned mode emulation are shown in the table below.
Argument | Value | Description |
---|---|---|
zoned | 0 or 1 | Disable or enable zoned mode (default: disabled) |
zone_size | size in MiB | Zone size to emulate (default: 256) |
zone_nr_conv | number | Number of conventional zones to emulate (default: 0 ) |
The following script shows how the configfs interface can be used to create scripts for easily creating emulated zoned block devices with different zone configurations.
#!/bin/bash
if [ $# != 4 ]; then
echo "Usage: $0 <sect size (B)> <zone size (MB)> <nr conv zones> <nr seq zones>"
exit 1
fi
scriptdir=$(cd $(dirname "$0") && pwd)
modprobe null_blk nr_devices=0 || return $?
function create_zoned_nullb()
{
local nid=0
local bs=$1
local zs=$2
local nr_conv=$3
local nr_seq=$4
cap=$(( zs * (nr_conv + nr_seq) ))
while [ 1 ]; do
if [ ! -b "/dev/nullb$nid" ]; then
break
fi
nid=$(( nid + 1 ))
done
dev="/sys/kernel/config/nullb/nullb$nid"
mkdir "$dev"
echo $bs > "$dev"/blocksize
echo 0 > "$dev"/completion_nsec
echo 0 > "$dev"/irqmode
echo 2 > "$dev"/queue_mode
echo 1024 > "$dev"/hw_queue_depth
echo 1 > "$dev"/memory_backed
echo 1 > "$dev"/zoned
echo $cap > "$dev"/size
echo $zs > "$dev"/zone_size
echo $nr_conv > "$dev"/zone_nr_conv
echo 1 > "$dev"/power
echo mq-deadline > /sys/block/nullb$nid/queue/scheduler
echo "$nid"
}
nulldev=$(create_zoned_nullb $1 $2 $3 $4)
echo "Created /dev/nullb$nulldev"
This script (nullblk-zoned.sh) takes four arguments: the emulated device sector size in bytes, the device zone size in MiB, the number of conventional zones (which can be 0) and the number of sequential write required zones. Memory backing for writen sectors is turned on with this script (memory_backed=1) which enables run-time persistancy of the data in the writen sectors of the device. The writen data is lost when the emulated device is deleted.
For example, a small zoned device with 4 conventional zones and 8 sequential write required zones of 64 MiB can be created with the following command.
# nullblk-zoned.sh 4096 64 4 8
Created /dev/nullb0
# blkzone report /dev/nullb0
start: 0x000000000, len 0x020000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
start: 0x000020000, len 0x020000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
start: 0x000040000, len 0x020000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
start: 0x000060000, len 0x020000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
start: 0x000080000, len 0x020000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
start: 0x0000a0000, len 0x020000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
start: 0x0000c0000, len 0x020000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
start: 0x0000e0000, len 0x020000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
start: 0x000100000, len 0x020000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
start: 0x000120000, len 0x020000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
start: 0x000140000, len 0x020000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
start: 0x000160000, len 0x020000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
The following script is the counter part of the zoned block device creationg script show above. It can be used to destroy created null_blk devices.
#!/bin/bash
if [ $# != 1 ]; then
echo "Usage: $0 <nullb ID>"
exit 1
fi
nid=$1
if [ ! -b "/dev/nullb$nid" ]; then
echo "/dev/nullb$nid: No such device"
exit 1
fi
echo 0 > /sys/kernel/config/nullb/nullb$nid/power
rmdir /sys/kernel/config/nullb/nullb$nid
echo "Destroyed /dev/nullb$nid"