SPDK block device及其编程的简单介绍

SPDK基于用户态,轮询、异步、无锁的NVMe驱动,封装且提供了一层关于块设备 (bdev) 的库。同时,块设备支持多层抽象与集成从而实现块设备组件 (bdev module) ,因此用户也可以根据自己的需求,编写出需要的bdev module。本文将聚焦于SPDK的块设备层 (bdev layer) 和块设备组件两个部分,并且以bdev raid module 为例,让读者更深入的认识SPDK bdev。

一. SPDK bdev layer

块设备是一种支持固定大小数据块读写的存储设备。通常一个块 (Block) 的大小是512或者4096字节 (512B or 4KiB) 。一个块设备可以是逻辑上的设备,也可以对应一个物理上的存储设备,比如NVMe SSD。SPDK中的bdev layer集成在目录spdk/lib/bdev之中,主要头文件为spdk/include/spdk/bdev.h,其中包含了与bdev进行交互的所有函数的声明。下面两张表分别是在操作bdev过程中涉及的主要数据结构和函数(Commit ID=ae3a9b8f08de94e95f6ee700d4901903bc898bd9)。

struct spdk_bdev 代表bdev的数据结构,记录一个bdev的名称,块大小,编号等基本属性,也记录有bdev在活跃期间的一些数据比如I/O总数,另外还记录有bdev所属的组件 (module) 以及和bdev操作相关的一张 function table.
struct spdk_bdev_desc 一个描述符,代表bdev的一个handle,通过descriptor可以获得对应bdev的指针或者打开一个bdev,类似于UNIX系统中的文件描述符一,个bdev上可以挂载多个spdk_bdev_desc,因此不同的线程可以使用同一个bdev,对应的,在关闭bdev时,需要保证没有bdev_desc挂载在bdev上。
struct spdk_bdev_io 代表发送给bdev的异步I/O。每一个I/O都需要通过spdk_io_channel 来传递。I/O中数据的封装形式主要是struct iovec。spdk_bdev_io 也有多种类型,其中最常用的就是两种类型:read 和write。
struct spdk_io_channel spdk_thread(线程) 和io_device(设备)进行I/O的通道,是spdk中抽象出的一种通信机制,spdk_bdev是一种较常用的io_device。通常一个spdk_io_channel只对应一个线程和一个块设备。spdk_bdev的I/O操作都是通过spdk_io_channel传递的。

上面四个结构体的关系图大致如下:

void spdk_bdev_initialize() 初始化spdk_bdev的函数,但是在调用前必须先初始化一些bdev的options, 该函数一般在初始化SPDK环境时调用。用以初始化配置文件中的bdev。
void spdk_bdev_open() 或 void spdk_bdev_open_ext() 打开一个spdk_bdev获得它的I/O操作权限。在打开时可以指定对该spdk_bdev的读写权限: 通过指定参数 write的值,如果为true,则该spdk_bdev可读/写,如果为false则只可读。该函数通过参数返回一个spdk_bdev_desc, 指向对应打开的spdk_bdev。
void spdk_bdev_close() 关闭一个spdk_bdev设备,或者归还一个spdk_bdev_desc的使用权。传入的参数是一个spdk_bdev_desc, 即spdk_bdev的描述符。如果程序不再使用某spdk_bdev或者程序即将结束时可调用该函数,归还当前进程对该spdk_bdev的使用权。
void spdk_bdev_get_io_channel() 通过传入spdk_bdev_desc, 获得对应的spdk_bdev的io_channel。如果当前线程已经存在一个为当前bdev设置的io_channel, 则返回该io_channel(线程和I/O channel的关系详见之前的微信文章);否则当前线程为该bdev创建一个io_channel并绑定到该线程。
void spdk_bdev_write() 或void spdk_bdev_writev() 函数的参数中指定写入的bdev、对应的io_channel、存放写数据的buffer、buffer中数据的位置(偏移量)与长度,以及一个可选的回调函数及其参数cb_arg。该函数会将buffer中的数据转化为块数据,以此来适应bdev读写,并调用spdk_bdev_write_blocks() 或spdk_bdev_writev_blocks()函数。这两个函数的区别在于后者可以支持使用scatter gather list的块设备。
参数中提到的回调函数的主要作用是在write操作完成以后,完成一些指定的动作。该回调函数的命名无限制,但是其接受的参数有限制:
第1个参数是本次写操作所用到spdk_bdev_io,在函数回调函数中必须要释放其所占用的空间,一般是使用spdk_bdev_free_io()函数完成。
第2个参数是一个bool值,代表本次写操作的完成情况,true代表完成,false代表失败。
第3个参数是一个void指针,指向和回调函数一起传入的参数cb_arg。
void spdk_bdev_write_blocks()或void spdk_bdev_writev_blocks() 函数的参数中指定写入的bdev、对应的io_channel、存放写数据的buffer、存放meta data的mdbuffer(可选)、buffer中数据偏移量和大小(均以块个数为单位),以及一个回调函数及其参数。两个函数的区别同上,所接受的回调函数的作用也同上所述。
void spdk_bdev_read()或void spdk_bdev_readv() 和spdk_bdev_write(spdk_bdev_writev)相对应的函数,完成读数据的功能。
void spdk_bdev_read_blocks()或void spdk_bdev_readv_blocks() 和spdk_bdev_write_blocks(spdk_bdev_writev_blocks)相对应的函数,完成读数据块的功能。
void spdk_bdev_free_io
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SPDK(存储性能开发套件)官方文档中文版。 第一章 简介 1 1.1.什么是SPDK? 1 1.2.入门 1 1.3. Vagrant开发环境 3 1.4.更新日志(略) 6 第二章 概念 6 2.1. 用户空间驱动程序** 6 2.2. 来自用户空间的DMA** 7 2.3. 消息传递和并发** 9 2.4. NAND Flash SSD内部 13 2.5. 将I / O提交到NVMe设备** 15 2.5.1 NVMe规范 15 2.5.2 SPDK NVMe驱动程序I / O路径 15 2.6. 使用Vhost-user进行虚拟化I / O. 16 2.6.1 介绍 16 2.6.2 QEMU 17 2.6.3 设备初始化 18 2.6.4 I / O路径 19 2.6.5 SPDK优化 20 2.7. SPDK目录结构概述 20 2.8. SPDK移植指南 22 第三章 用户指南 22 3.1. 系统配置用户指南 22 3.1.1 IOMMU配置 22 3.2. SPDK应用程序概述 23 3.2.1 配置SPDK应用程序 23 3.3. iSCSI Target 26 3.3.1. iSCSI Target入门指南 26 3.3.2. 通过配置文件配置iSCSI Target 27 3.3.3. 通过RPC方法配置iSCSI Target 28 3.3.4. 配置iSCSI启动器 29 3.3.5. rpc配置示例*** 30 3.3.6. iSCSI 热插拔 32 3.4. NVMe over Fabrics Target 32 3.5. Vhost Target(略) 37 3.6 块设备用户指南 38 3.6.1 bdev介绍 38 3.6.2 通用RPC命令 38 3.6.3 Ceph RBD 39 3.6.4 压缩虚拟Bdev模块 40 3.6.5 加密虚拟Bdev模块 41 3.6.6 延迟vbdev模块 41 3.6.7 GPT(GUID分区表) 42 3.6.8 iSCSI bdev 43 3.6.9 Linux AIO bdev 43 3.6.10 OCF虚拟bdev 43 3.6.11 Malloc bdev 44 3.6.12 NULL bdev 44 3.6.13 NVMe bdev 44 3.6.14 逻辑卷Lvol 45 3.6.15 RAID 46 3.6.16 Passthru 46 3.6.17 Pmem 46 3.6.18 Virtio Block 47 3.6.19 Virtio SCSI 47 3.7 BlobFS(Blobstore文件系统) 48 3.7.1 RocksDB集成 48 3.7.2 FUSE插件 49 3.8 JSON-RPC方法(略) 49 第四章 程序员指南 49 4.1. Blobstore程序员指南 49 4.1.1 介绍 50 4.1.2 运作理论 50 4.1.3 设计注意事项 52 4.1.4 例子 54 4.1.5配置 54 4.1.6 组件细节 54 4.2. 块设备层编程指南 56 4.3 编写自定义块设备模块 58 4.3.1 介绍 58 4.3.2 创建一个新模块 59 4.3.3创建虚拟Bdev 60 4.4 NVMe over Fabrics目标编程指南 61 4.4.1 介绍 61 4.4.2 原语结构体 61 4.4.3 基础函数 62 4.4.4访问控制 62 4.4.5发现子系统 62 4.4.6 传输 63 4.4.7选择线程模型 63 4.4.8 跨CPU核心扩展 63 4.4.9 零拷贝支持 63 4.4.10 RDMA 63 4.5 Flash传输层 64 4.5.1 术语 64 4.5.2 使用方法 67 4.6 GDB宏用户指南 69 4.6.1 介绍 69 4.6.2 加载gdb宏 71 4.6.3 使用gdb数据目录 72 4.6.4 使用.gdbinit加载宏 72 4.6.5 为什么我们需要显式调用spdk_load_macros 72 4.6.6 以上可用的宏总结 73 4.6.7 添加新宏 73 4.7 SPDK “Reduce”块压缩算法 73 4.7.1 介绍 73 4.7.2 例子 74 4.8 通知库 78 第五章 基本信息 79 5.1 事件框架 79 5.1.1 事件框架设计注意事项 80 5.1.2 SPDK事件框架组件 80 5.1.3 应用框架 80 5.2 逻辑卷 81 5.2.1 术语 81 5.2.2 配置逻辑卷 84 5.3 矢量数据包处理(略) 86 第六章 杂项 86 6.1 介绍 86 6.2 NVMe的P2P API 86 6.3 确定设备支持 87 6.4 P2P问题 87 第七章 驱动程序 88 7.1 NVMe驱动程序*** 88 7.1.1 介绍 88 7.1.2 例子 88 7.1.3 公共接口 89 7.1.4 NVMe驱动程序设计 89 7.1.5 NVMe over Fabrics主机支持 91 7.1.6 NVMe多进程 91 7.1.7 NVMe Hotplug 92 7.2 I/OAT驱动程序 93 7.2.1 公共接口 93 7.2.2 关键功能 93 7.3 Virtio驱动程序 93 7.3.1 介绍 93 7.3.2 2MB大页面 93 第八章 工具 94 8.1 SPDK CLI 94 8.1.1 安装所需的依赖项 94 8.1.2 运行SPDK应用程序实例 94 8.1.3 运行SPDK CLI 94 8.1.4 可选 - 创建Python虚拟环境 94 8.2 nvme-CLI 95 8.2.1 nvme-cli with SPDK入门指南 95 8.2.2 使用场景 95 第九章 性能测试报告(略) 96 第十章NVMe-oF Target跟踪点*** 96 10.1 介绍 96 10.2 启用跟踪点 97 10.3 捕获事件的快照 97 10.4 捕获足够的跟踪事件 98 10.5 添加新的跟踪点 99

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值