在虚拟机中搭建ZNS SSD实验环境并通过rocksdb进行测试。
Nvmevirt是一款比较新的SSD 仿真器(emulator),通过内核模块来模拟ZNS SSD,论文中性能更好,模拟的准确度更接近真实设备,且支持kv-ssd。
在NVMeVirt可以通过Makefile中不同的参数配置SSD类型,也可以在ssd_config里配置SSD参数。
Zenfs是rocksdb的一个插件,可以减少系统写放大,支持ZNS,自带性能测试工具。
推荐直接使用Ubuntu 22.10,Kernel相关配置不用再更改。
低版本内核需要进行编译,使用Zenfs需要Linux 内核5.9以上,使用NVMeVirt需要内核版本5.15以上。
非Ubuntu22.10进行编译内核过程中可能需要开启内核选项,在enable the block layer中开启Zoned block device support或者在.config中修改CONFIG_BLK_DEV_ZONED为y,在IO scheduler中修改为MQ deadline。
编译过程中容易报错
make[1]: *** No rule to make target 'debian/canonical-certs.pem', needed by 'certs/x509_certificate_list'. Stop.
make: *** [Makefile:1868: certs] Error 2
在命令行中执行
scripts/config --disable SYSTEM_TRUSTED_KEYS
如果报错 canonical-revoked-certs.pem:
make[1]: *** No rule to make target 'debian/canonical-revoked-certs.pem', needed by 'certs/x509_revocation_list'. Stop.
make: *** [Makefile:1868: certs] Error 2
在命令行中执行:
scripts/config --disable SYSTEM_REVOCATION_KEYS
Compiling the kernel 5.11.11
编译内核报错 No rule to make target ‘debian/canonical-certs.pem‘ 或 ‘canonical-revoked-certs.pem‘ 的解决方法
Zenfs需要依赖比较多的库,容易踩坑,如果出现gflags,snappy等库未安装的提示,安装完相应的库后需要将 plugin/zenfs/util以及rocksdb下的文件都make clean后再make。
需要make clean后再make!
需要make clean后再make!
需要make clean后再make!
按照Zenfs页面,先安装libzbd
libzbd库依赖于以下几个包:
sudo apt install m4 autoconf automake libtool
之后就可以按照libzbd官方文档说明安装了
libzbd编译
$ sh ./autogen.sh
$ ./configure
$ make
libzbd安装
$ sudo make install
如果在/usr/lib(或/usr/lib64) 下找到libzbd.a等库文件证明安装成功。库头文件安装在/usr/include/libzbd.
示例应用程序的可执行文件安装在 /usr/bin.
libzbd安装
安装好所有的库再进行编译,否则需要安装库之后make clean后再进行编译
# 基本的编译工具等不过多介绍
sudo apt install build-essential
sudo apt install pkg-config
# 压缩库
sudo apt install libsnappy-dev
安装gflags
git clone https://github.com/gflags/gflags.git
mkdir build
cmake ..
make
make install
gflags安装
Zenfs
下载源码
$ git clone https://github.com/facebook/rocksdb.git
$ cd rocksdb
$ git clone https://github.com/westerndigitalcorporation/zenfs plugin/zenfs
Build and install rocksdb with zenfs enabled:
$ DEBUG_LEVEL=0 ROCKSDB_PLUGINS=zenfs make db_bench install
我这里make -j会报错,所以不推荐按官方的make -j48,把-j48删掉,等待时间会比较长
之后build zenfs utility
$ cd plugin/zenfs/util
$ make
至此Zenfs的环境就搭建完毕了,之后进行NvmeVirt的搭建。
修改/etc/default/grub
在GRUB_CMDLINE_LINUX行后加入
“memmap=64G\$128G”
这样将从 128GB 内存偏移开始保留 64GB 物理内存块(总共 192GB 物理内存)。
我的物理机内存比较小,都设置的4GB
更新grub
$ update-grub
$ reboot
重启后可以通过
$ sudo cat /proc/iomem
查看是否预留内存成功
内核启动参数memmap
预留内存成功后可以通过NVMeVirt模拟ZNS SSD啦
源码下载
$ git clone https://github.com/snu-csl/nvmevirt
可以修改Makefile进行SSD类型的更改,一次只能模拟一种SSD
# Select one of the targets to build
#CONFIG_NVMEVIRT_NVM := y
#CONFIG_NVMEVIRT_SSD := y
CONFIG_NVMEVIRT_ZNS := y
#CONFIG_NVMEVIRT_KV := y
修改为ZNS SSD
NVMe Virt本身的ZONE_SIZE设置为2GB,比较大,我进行了修改
通过修改ssd_config.h进行修改
我修改为32MB
之后就可以make了
正常输出如下信息
$ make
make -C /lib/modules/5.15.37/build M=/path/to/nvmev modules
make[1]: Entering directory '/path/to/linux-5.15.37'
CC [M] /path/to/nvmev/main.o
CC [M] /path/to/nvmev/pci.o
CC [M] /path/to/nvmev/admin.o
CC [M] /path/to/nvmev/io.o
CC [M] /path/to/nvmev/dma.o
CC [M] /path/to/nvmev/simple_ftl.o
LD [M] /path/to/nvmev/nvmev.o
MODPOST /path/to/nvmev/Module.symvers
CC [M] /path/to/nvmev/nvmev.mod.o
LD [M] /path/to/nvmev/nvmev.ko
BTF [M] /path/to/nvmev/nvmev.ko
make[1]: Leaving directory '/path/to/linux-5.15.37'
$
我的电脑输出如下信息
其中BTF的提示不用管,不影响使用。
之后可以通过加载内核模块.ko文件模拟ZNS SSD
由于NVMeVirt模拟ZNS SSD需要1MB空间记录信息,因此启动参数需要在ZNS SSD容量上+1M,启动命令如下
$ insmod nvmev.ko memmap_start=4G memmap_size=2049M cpus=0,1
查看是否模拟成功
$ dmesg
看到如下信息证明模拟成功
[ 1751.371339] nvmev: loading out-of-tree module taints kernel.
[ 1751.371399] nvmev: module verification failed: signature and/or required key missing - tainting kernel
[ 1751.378128] NVMeVirt: Storage : 100100000 + 80000000
[ 1751.379523] NVMeVirt: Total Capacity(GiB,MiB)=2,2112 chs=8 luns=32 lines=64 blk-size(MiB,KiB)=1,1056 line-size(MiB,KiB)=33,33792
[ 1751.381513] NVMeVirt: [chmodel_init] bandwidth 450 max_credits 14 tx_time 271
[ 1751.383483] NVMeVirt: [chmodel_init] bandwidth 450 max_credits 14 tx_time 271
[ 1751.398424] NVMeVirt: [chmodel_init] bandwidth 450 max_credits 14 tx_time 271
[ 1751.415916] NVMeVirt: [chmodel_init] bandwidth 450 max_credits 14 tx_time 271
[ 1751.432908] NVMeVirt: [chmodel_init] bandwidth 450 max_credits 14 tx_time 271
[ 1751.449557] NVMeVirt: [chmodel_init] bandwidth 450 max_credits 14 tx_time 271
[ 1751.466091] NVMeVirt: [chmodel_init] bandwidth 450 max_credits 14 tx_time 271
[ 1751.482771] NVMeVirt: [chmodel_init] bandwidth 450 max_credits 14 tx_time 271
[ 1751.483178] NVMeVirt: [chmodel_init] bandwidth 3050 max_credits 99 tx_time 40
[ 1751.483180] NVMeVirt: zone_size=33554432(Byte),32(MB), # zones=64 # die/zone=32
[ 1751.483183] NVMeVirt: [NVMEV_NAMESPACE_INIT] ns=0 ns_addr=00000000dc72fbc3 ns_size=2048(MiB)
[ 1751.483241] PCI host bridge to bus 0001:10
[ 1751.483243] pci_bus 0001:10: root bus resource [io 0x0000-0xffff]
[ 1751.483245] pci_bus 0001:10: root bus resource [mem 0x00000000-0x1fffffffffff]
[ 1751.483246] pci_bus 0001:10: root bus resource [bus 00-ff]
[ 1751.483253] pci 0001:10:00.0: [0c51:0101] type 00 class 0x010802
[ 1751.483256] pci 0001:10:00.0: reg 0x10: [mem 0x100000000-0x100003fff 64bit]
[ 1751.483258] pci 0001:10:00.0: reg 0x30: [mem 0x00000000-0x000007ff pref]
[ 1751.483259] pci 0001:10:00.0: enabling Extended Tags
[ 1751.490230] NVMeVirt: Successfully created virtual PCI bus (node 0)
[ 1751.496773] NVMeVirt: nvmev_io_worker_0 started on cpu 1 (node 0)
[ 1751.496961] NVMeVirt: Successfully created Virtual NVMe device
[ 1751.496987] NVMeVirt: nvmev_dispatcher started on cpu 0 (node 0)
[ 1751.506274] nvme nvme0: pci function 0001:10:00.0
[ 1751.508875] NVMeVirt: Handling NVME_LOG_SMART
[ 1751.515535] nvme nvme0: 16/0/0 default/read/poll queues
[ 1751.541689] NVMeVirt: Handling NVME_LOG_CMD_EFFECTS
$ lsblk 可以看到模拟出的ZNS SSD
#安装nvme-cli工具
$ apt install nvme-cli
#查看zone信息
$ nvme zns report-zones /dev/nvme0n1 <path to zoned block device>
可以看到number of zones:64 申请了2G的ZNS SSD,ZONE_SIZE为32MB,共有2048/32=64个zone
还可以通过nvme-cli进行zone的写入等操作,更多使用参见nvme-cli。
可以通过fio进行性能测试
$ cat /sys/class/block/<zoned block device>/queue/scheduler
# out [none] mq-deadline 说明目前IO调度是none
$ echo deadline > /sys/class/block/<zoned block device>/queue/scheduler
# out [mq-deadline] none 更改为deadline IO调度
创建Zenfs
$ cd rocksdb
$ ./plugin/zenfs/util/zenfs mkfs --zbd=<zoned block device> --aux_path=<path to store LOG and LOCK files>
# 正常会显示zenfs created
运行rocksdb测试工具
./db_bench --fs_uri=zenfs://dev:<zoned block device name> --benchmarks=fillrandom --use_direct_io_for_flush_and_compaction
在搭建过程中遇到了比较多的困难,相关资料也比较少,踩了不少坑,因此写的比较细,特别感谢利用 RocksDB + ZenFS 测试 ZNS 的环境搭建和使用博客的指导,多次在踩坑后发现少装了库然后重新安装,重新编译,最终搭建好环境。