53

Liblightnvm, 在用户态操作Open-Channel SSD

 5 years ago
source link: https://www.sdnlab.com/22976.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

作者简介:刘孝冬,存储软件工程师,主要从事SPDK以及ISA-L软件开发工作。

Open-Channel SSD 是由Host深度控制和维护的一种SSD. 相对于NVMe SSD, Host所能够看到的不再是一段逻辑块地址(Logical Block Address, LBA),而是间隔排列的NAND存储单元的物理页地址(Physical Page Address, PPA)。Open-Channel SSD 将内部NAND介质的诸多细节暴露给Host,由Host来实现自定义的FTL(Flash Translation Layer),根据实际工作负载的特点,最大化,且有区别的实现高吞吐,低时延,或IO隔离等特性。

LightNVM 是Linux 内核中操作Open-Channel SSD的子系统的名称,并作为实际操作Open-Channel SSD的driver。既然Open-Channel SSD的愿景是希望Host是基于实际工作负载的特点,来调配操作盘上NAND资源。那就意味着,开发者需要基于业务需求,灵活实现定制化的FTL。这些定制化的软件则更有可能会被实现在用户态,而非内核态。

由此,用户态定制化FTL需要一套能够提供操作Open-Channel SSD的API。从名称可知liblightnvm就是这样一套在用户态操作Open-Channel SSD的函数库。

Liblightnvm 的组成

libIightnvm 提供了Open-Channel SSD与用户空间交互的方法,和获取信息的手段。它的组成部分由图1所示

001.jpg

Figure 1 liblightnvm的组成部分

1.liblightnvm.a与相关头文件

它的核心是函数库 liblightnvm.a与相关头文件 , 其中定义了Open-Channel SSD所需的各种结构,向上提供出封装好的nvm_dev_XXX和nvm_cmd_XXX系列函数。

  • nvm_dev_XXX用于打开、关闭Open-Channel SSD,获取盘上资源信息,设置相关配置。
  • nvm_cmd_XXX用于执行相关的admin命令和IO命令。

为了简便用户态应用 操作Open-Channel SSD,函数库 liblightnvm.a与相关头文件也包含了基本的辅助功能, nvm_addr_XXX,nvm_buf_XXX,以及nvm_vblk_XXX系列函数。

  • nvm_buf_XXX封装了内存申请、释放填充等操作。由于liblightnvm的后端对内存类型有不同的需求,使用nvm_buf系列API可以屏蔽掉不同类型内存操作的差异。
  • nvm_addr_XXX 包括了很多非常方便的地址转换结构的方法。Open-Channel 涉及到的地址表示方法主要有4类:NAND成员结构地址(Generic address, gen), 设备物理页地址 (device physical page address, dev), Chunk信息偏移地址(Chunk information log page offset, lpo), 以及块设备偏移地址(Linux Block Device offset, off)。
  • nvm_vblk_XXX包括了对Virtual Block的定义和操作。

2.liblightnvm的后端nvm_be

Liblightnvm 将具体的执行过程隐藏在不同的后端nvm_be中。当前liblightnvm的nvm_be有多个,nvm_be_ioctl、nvm_be_lbd 和nvm_be_spdk.

  • nvm_be_ioctl是使用ioctl系统调用来与kernel内的lightnvm (Open-Channel SSD的内核驱动)交互,操作Open-Channel SSD.
  • nvm_be_lbd的admin 命令与nvm_be_ioctl 相同,通过ioctl系统调用实现。但是read/write/earse这些IO命令则是通过操作linux 块设备实现。
  • nvm_be_spdk是通过直接调用SPDK中的nvme driver,完全在用户态执行的后端。

nvm_be 可以在运行时指定liblightnvm分别为每个nvm_be指定一个Identifier, 在打开nvm_dev时,传入对应nvm_be的Identifier, 对该nvm_dev的操作就通过该Identifier对应的nvm_be执行。如果是使用几个liblightnvm 附带的命令行工具,可以通过环境变量NVM_CLI_BE_ID的值来指定nvm_be.

例如:NVM_CLI_BE_ID=0x2 nvm_dev info /dev/nvme0n1
就会通过nvm_be_lbd后端来执行geometry命令获取设备信息。

Java
dev_attr: verid: 0x02 be_id: 0x10 name: '' path: '' fd: 0 ssw: 12 mccap: 11111111111111111111111111111110 pmode: 'SNGL' erase_naddrs_max: 64 read_naddrs_max: 64 write_naddrs_max: 64 meta_mode: 0 bbts_cached: 0 bbts_cached: 00000000 quirks: 00000000 dev_geo: verid: 0x02 npugrp: 8 npunit: 8 nchunk: 501 nsectr: 18432 nbytes: 4096 nbytes_oob: 0 tbytes: 2420750942208 tmbytes: 2308608 dev_ppaf: ~ dev_ppaf_mask: ~ dev_lbaf: pugrp: 3 punit: 3 chunk: 9 sectr: 15 dev_lbaz: pugrp: 27 punit: 24 chunk: 15 sectr: 0 dev_lbam: pugrp: '0000000000000000000000000000000000111000000000000000000000000000' punit: '0000000000000000000000000000000000000111000000000000000000000000' chunk: '0000000000000000000000000000000000000000111111111000000000000000' sectr: '0000000000000000000000000000000000000000000000000111111111111111'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
dev_attr:
  verid:0x02
  be_id:0x10
  name:''
  path:''
  fd:0
  ssw:12
  mccap:11111111111111111111111111111110
  pmode:'SNGL'
  erase_naddrs_max:64
  read_naddrs_max:64
  write_naddrs_max:64
  meta_mode:0
  bbts_cached:0
  bbts_cached:00000000
  quirks:00000000
dev_geo:
  verid:0x02
  npugrp:8
  npunit:8
  nchunk:501
  nsectr:18432
  nbytes:4096
  nbytes_oob:0
  tbytes:2420750942208
  tmbytes:2308608
dev_ppaf:~
dev_ppaf_mask:~
dev_lbaf:
  pugrp:3
  punit:3
  chunk:9
  sectr:15
dev_lbaz:
  pugrp:27
  punit:24
  chunk:15
  sectr:0
dev_lbam:
  pugrp:  '0000000000000000000000000000000000111000000000000000000000000000'
  punit:  '0000000000000000000000000000000000000111000000000000000000000000'
  chunk:  '0000000000000000000000000000000000000000111111111000000000000000'
  sectr:  '0000000000000000000000000000000000000000000000000111111111111111'

3.命令行工具

为了方便用户评估和调试Open-Channel SSD,liblightnvm的源代码中还附带了几个命令行工具。这些工具也同时作为示例,展示了liblightnvm API的使用方法。

  • nvm_dev 命令可以获得当前系统上所有的Open-Channel SSD, 也可以获取某个SSD的Geometry信息。
  • num_addr命令可以灵活的计算Open-Channel SSD涉及的各种不同的地址格式。
  • nvm_cmd 命令可以直接在某个Open-Channel SSD上执行admin 或者IO 命令。
  • nvm_vblk 命令可以以Virtual Block 为基本单位做read/write/erase等IO 操作。作为对nvm_cmd命令的补充,它在操作Virtual Block时省去了nvm_cmd繁琐的步骤。
  • nvm_bbt命令只能用在支持Open-Channel Spec 1.2的设备。bbt, 即 bad block table,在Spec 1.2中起到了类似 Spec 2.0中chunk information的作用。

4.异步调用

为了提高liblightnvm对用户态应用的可用性,目前liblightnvm中加入几个简单的异步调API. 它们的名称和作用分别是:

002.jpg

Liblightnvm中需要区别的概念

1.多样的地址表示

NAND成员结构地址(gen addr)是一个结构体,结构体表示了SSD的NAND物理结构。比如,Open-Chanel Spec 1.2 和Spec 2.0的地址结构分别是:

003.jpg
004.png

设备物理页地址(dev addr)是一个64位的无符号整数。 这个地址类型与PPA(Physical Page Address)对应。上面在介绍NAND成员地址中,每个成员的长度,由liblightnvm默认定义, 但是在Open-Channel SSD上,实际的长度格式由固件上定义,并通过Geometry 命令来获取。所以该地址类型的具体值由gen地址和固件长度格式共同决定。比如, 对一个Spec 2.0的gen地址:

Java
gen addr: { pugrp: 04, punit: 02, chunk: 0142, sectr: 0000 }
1
gen addr:{    pugrp:04,punit:02,chunk:0142,sectr:0000  }

它直接对应的16进制整数值为 :0x0402008e00000000

若某个SSD的固件长度格式是:

Java
dev_lbaf: {pugrp: 3, punit: 3, chunk: 9, sectr: 15}
1
dev_lbaf:{pugrp:3,punit:3,chunk:9,sectr:15}

则,上述gen addr 对应的dev addr的二进制为:100 010 010001110 000000000000000B,
即0010 0010 0100 0111 0000 0000 0000 0000B

十六进制值为:0x22470000.

Dev addr 即对应了设备的PPA,Open-Channel SSD 的所有IO命令都需要使用它。

  • 块设备偏移地址(off addr),即为以字节为单位偏移的地址。其值为dev addr 左移到页大小。比如如果SSD的页大小为4KB(212B),则off addr 为 dev addr 左移12位。
  • Chunk信息偏移地址(lpo addr),主要用在Spec 2.0中,当要获取chunk信息时,需要指定对应的lpo。由于Chunk 信息按照Chunk位置顺序排列,中间没有地址空洞,所以某个chunk信息的位置是无法通过dev addr或gen addr指定,必须通过gen addr 与SSD上各种NAND组织数量来确定。

005.jpg

Figure 2 Chunk Information的布局图

2.何为Virtual Block

Block 是一个相当魔幻的词。通常存储里面讲一个Block,是指一个逻辑块,块存储的最小操作单位。但在NAND的相关术语中,Block通常指擦除单位,而读写的单位常是Page或Sector,一个NAND Block由大量的NAND Page组成。Open-Channel Spec 1.2里面,Block的含义遵从NAND术语,代表擦除单位NAND Block。到了Open-Channel Spec 2.0,为了避免Block混淆,用Chunk代替Block来表示擦除单位。Liblightnvm为了保持命名的连贯统一,函数,参数,及结构成员名称依旧保持Block 或blk。

006.jpg

Figure 3 one Virtual Block in Open-Channel SSD

说回到Virtual Block, 它是一组NAND 擦除单位Block的集合。如图3,为了获得高读写IOPS或吞吐量,其中的每个Block都分布在不同的Channel和LUN中,使得一个读写请求可以有机会并行地在各个Block上同时执行。例如,写一个Block的Throughput 是 200MB/s, 写一个由8个Block组成的Virtual Block 的Throughput则是1600MB/s。为了简化对组成Virtual Block中Block的记录维护,常常默认每个Block在各自的LUN中有着同样的offset。定制化的FTL,明智的选择都是以Virtual Block整体来作IO操作。

References
[1] Open-Channel Solid State Drives Specification Revision 1.2
[2] Open-Channel Solid State Drives Specification Revision 2.0
[3] Lightnvm: The Linux Open-Channel SSD subsystem.
[4] https://github.com/OpenChannelSSD/liblightnvm/
[5] http://lightnvm.io


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK