介紹
SPDK Bdev架構
SPDK塊設備層(通常簡稱為bdev)是一個C庫,旨在等同於操作系統塊存儲層,該層通常位於傳統內核存儲堆棧中設備驅動程序的正上方。具體來說,此庫提供以下功能:
- 一種可插拔模塊API,用於實現與不同類型的塊存儲設備連接的塊設備。
- NVMe,malloc(ramdisk),Linux AIO,virtio-scsi,Ceph RBD,Pmem和Vhost-SCSI Initiator等驅動程序模塊。
- 用於枚舉和聲明SPDK塊設備,然后在這些設備上執行操作(讀取,寫入,取消映射等)的應用程序API。
- 堆棧塊設備以創建復雜I / O管道的工具,包括邏輯卷管理(lvol)和分區支持(GPT)。
- 通過JSON-RPC配置塊設備。
- 請求排隊,超時和重置處理。
- 多個無鎖隊列,用於將I / O發送到塊設備。
Bdev模塊創建抽象層,為所有設備提供通用API。用戶可以使用可用的bdev模塊或使用下面任何類型的設備創建自己的模塊(有關詳細信息,請參閱編寫自定義塊設備模塊)。SPDK還提供了vbdev模塊,可在現有的bdev上創建塊設備。例如邏輯卷或SPDK GPT分區表
先決條件
假設已經在平台上構建標准SPDK分發版。塊設備層是一個C庫,其中包含一個名為bdev.h的公共頭文件。以下章節中描述的所有SPDK配置都是使用JSON-RPC命令完成的。SPDK提供了一個基於python的命令行工具,用於發送位於的RPC命令scripts/rpc.py
。用戶可以通過使用-h
或--help
標記運行此腳本來列出可用命令。此外,用戶可以通過運行直接從SPDK應用程序檢索當前支持的RPC命令集scripts/rpc.py get_rpc_methods
。通過添加-h
flag作為命令參數,可以顯示每個命令的詳細幫助。
通用RPC
get_bdevs
可以使用get_bdevs
RPC命令獲取當前可用的塊設備列表,包括有關它們的詳細信息。用戶可以添加可選參數name
以獲取該名稱bdev指定的詳細信息。
response示例
set_bdev_qos_limit
用戶可以使用set_bdev_qos_limit
RPC命令在現有bdev上啟用,調整和禁用速率限制。支持兩種類型的速率限制:IOPS和帶寬。可以隨時為指定的bdev啟用,調整和禁用速率限制。bdev名稱是此RPC命令的必需參數,rw_ios_per_sec
並且rw_mbytes_per_sec
必須至少指定其中一個。啟用兩個速率限制后,第一個滿足限制將生效。可以指定值0以禁用相應的速率限制。用戶可以使用-h
或運行此命令以--help
獲取更多信息。
delete_bdev
要刪除以前創建的bdev用戶,可以使用delete_bdev
RPC命令。可以隨時刪除Bdev,這將由任何上層完全處理。作為參數,用戶應提供bdev名稱。此RPC命令應僅用於調試目的。要刪除特定的bdev,請使用特定於其bdev模塊的delete命令。
Ceph RBD
SPDK RBD bdev驅動程序提供對Ceph RADOS塊設備(RBD)的SPDK塊層訪問。通過librbd和librados庫訪問Ceph RBD設備,以訪問Ceph導出的RADOS塊設備。要創建Ceph,construct_rbd_bdev
應該使用bdev RPC命令。
示例命令
rpc.py construct_rbd_bdev rbd foo 512
此命令將創建一個bdev,表示來自名為'rbd'的池中的'foo'圖像。
要刪除塊設備表示,請使用delete_rbd_bdev命令。
rpc.py delete_rbd_bdev Rbd0
Crypto Virtual Bdev模塊
加密虛擬bdev模塊可以配置為為任何底層bdev提供靜態數據加密。該模塊依賴DPDK CryptoDev框架來提供所有加密功能。該框架僅支持許多不同的軟件加密模塊以及英特爾QAT板的硬件輔助支持。該框架還提供對密碼,散列,身份驗證和AEAD功能的支持。此時SPDK虛擬bdev模塊僅支持密碼,如下所示:
- AESN-NI多緩沖加密輪詢模式驅動程序:RTE_CRYPTO_CIPHER_AES128_CBC
- 英特爾(R)QuickAssist(QAT)加密輪詢模式驅動程序:RTE_CRYPTO_CIPHER_AES128_CBC(注意:QAT功能正常,但在硬件與SPDK CI系統完全集成之前,標記為實驗性。)
為了支持使用bdev塊偏移量(LBA)作為初始化向量(IV),加密模塊將所有I / O分解為大小等於底層bdev的塊大小的加密操作。例如,具有512B塊大小的bdev的4K I / O將導致8次加密操作。
對於讀取,提供給加密模塊的緩沖區將用作未加密數據的目標緩沖區。但是,對於寫入,臨時暫存緩沖區用作加密的目標緩沖區,然后作為寫緩沖區傳遞給底層bdev。這樣做是為了避免加密原始源緩沖區中的數據,這可能在某些用例中引起問題。
示例命令
rpc.py construct_crypto_bdev -b NVMe1n1 -c CryNvmeA -d crypto_aesni_mb -k 0123456789123456
此命令將在NVMe bdev“NVMe1n1”之上創建一個名為“CryNvmeA”的加密vbdev,並將使用DPDK軟件驅動程序“crypto_aesni_mb”和密鑰“0123456789123456”。
要刪除vbdev,請使用delete_crypto_bdev命令。
rpc.py delete_crypto_bdev CryNvmeA
GPT(GUID分區表)
GPT虛擬bdev驅動程序默認啟用,不需要任何配置。它將自動檢測任何連接的bdev上的SPDK GPT分區表,並可能創建多個虛擬bdev。
SPDK GPT分區表
SPDK分區類型GUID是7c5222bd-8f5d-4087-9c00-bf9843c7b58c
。現有的SPDK bdev可以通過NBD公開為Linux塊設備,然后使用標准分區工具進行分區。分區后,需要刪除bdev並再次附加,以便GPT bdev模塊查看任何更改。必須先加載NBD內核模塊。要創建NBD,bdev用戶應該使用start_nbd_disk
RPC命令。
示例命令
rpc.py start_nbd_disk Malloc0 /dev/nbd0
這將Malloc0
在/dev/nbd0
塊設備下公開SPDK bdev 。
要刪除NBD設備,用戶應使用stop_nbd_disk
RPC命令。
示例命令
rpc.py stop_nbd_disk /dev/nbd0
要顯示完整或指定的nbd設備列表,用戶應使用get_nbd_disks
RPC命令。
示例命令
rpc.py stop_nbd_disk -n /dev/nbd0
使用NBD創建GPT分區表
iSCSI bdev
SPDK iSCSI bdev驅動程序依賴於libiscsi,因此默認情況下不啟用。要使用它,請使用額外的--with-iscsi-initiator
配置選項構建SPDK 。
以下命令iSCSI0
從iqn.2016-06.io.spdk:init
作為報告的啟動器IQN的給定iSCSI URL公開的單個LUN 創建bdev 。
rpc.py construct_iscsi_bdev -b iSCSI0 -i iqn.2016-06.io.spdk:init --url iscsi://127.0.0.1/iqn.2016-06.io.spdk:disk1/0
URL的格式如下: iscsi://[<username>[%<password>]@]<host>[:<port>]/<target-iqn>/<lun>
Linux AIO bdev
Linux 異步 I/O 是 Linux 內核中提供的一個相當新的增強。它是 2.6 版本內核的一個標准特性,但是我們在 2.4 版本內核的補丁中也可以找到它。AIO 背后的基本思想是允許進程發起很多 I/O 操作,而不用阻塞或等待任何操作完成。稍后或在接收到 I/O 操作完成的通知時,進程就可以檢索 I/O 操作的結果。
SPDK AIO bdev驅動程序通過Linux AIO提供對Linux內核塊設備的SPDK塊層訪問或Linux文件系統上的文件。請注意,使用了O_DIRECT,因此繞過了Linux頁面緩存。此模式可能與基於內核的典型目標接近,因為用戶空間目標可以在不使用用戶空間驅動程序的情況下獲得。要創建AIO,construct_aio_bdev
應使用bdev RPC命令。
示例命令
rpc.py construct_aio_bdev /dev/sda aio0
此命令aio0
將從/ dev / sda 創建設備。
rpc.py construct_aio_bdev /tmp/file file 8192
此命令file
將從/ tmp / file 創建塊大小為8192的設備。
要刪除aio bdev,請使用delete_aio_bdev命令。
rpc.py delete_aio_bdev aio0
Malloc bdev
malloc bdevs是ramdisks。由於它的性質,它們是不穩定的。它們是從為SPDK應用程序提供的巨大頁面內存創建的。
NULL
SPDK null bdev驅動程序是一個虛擬塊I / O目標,它會丟棄所有寫入並返回未定義的讀取數據。它可以用最小的塊設備開銷對bdev I / O堆棧的其余部分進行基准測試,並用於測試使用Malloc bdev無法輕松創建的配置。要創建Null bdev,應該使用construct_null_bdevRPC命令。
示例命令
rpc.py construct_null_bdev Null0 8589934592 4096
此命令將創建一個Null0
塊大小為4096 的8 PB的設備。
要刪除null bdev,請使用delete_null_bdev命令。
rpc.py delete_null_bdev Null0
NVMe bdev
有兩種方法可以在SPDK中基於NVMe設備創建塊設備。第一種方式是連接本地PCIe驅動器,第二種方法是連接NVMe-oF設備。在這兩種情況下,用戶都應使用construct_nvme_bdev
RPC命令來實現這一點。
示例命令
rpc.py construct_nvme_bdev -b NVMe1 -t PCIe -a 0000:01:00.0
此命令將在系統中創建物理設備的NVMe bdev。
rpc.py construct_nvme_bdev -b Nvme0 -t RDMA -a 192.168.100.1 -f IPv4 -s 4420 -n nqn.2016-06.io.spdk:cnode1
此命令將創建NVMe-oF資源的NVMe bdev。
要刪除NVMe控制器,請使用delete_nvme_controller命令。
rpc.py delete_nvme_controller Nvme0
此命令將刪除名為Nvme0的NVMe控制器。
邏輯卷
Logical Volumes庫是一個靈活的存儲空間管理系統。它允許在其他bdev之上創建和管理具有可變大小的虛擬塊設備。SPDK邏輯卷庫建立在Blobstore程序員指南之上。有關詳細說明,請參閱邏輯卷。
邏輯卷存儲
在創建任何邏輯卷(lvols)之前,必須首先在選定的塊設備上創建lvol存儲。Lvol商店是lvols容器,負責管理lvol bdevs的底層bdev空間分配和存儲元數據。要創建lvol存儲,用戶應該使用construct_lvol_store
RPC命令。
示例命令
rpc.py construct_lvol_store Malloc2 lvs -c 4096
這將創建lvs
以簇大小4096 命名的Malloc2
lvol 存儲,構建在bdev之上。作為響應,將向用戶提供uuid,這是唯一的lvol商店標識符。
用戶可以使用get_lvol_stores
RPC命令獲取可用的lvol存儲列表(沒有可用的參數)。
response示例
要刪除lvol store,用戶應該使用destroy_lvol_store
RPC命令。
示例命令
rpc.py destroy_lvol_store -u 330a6ab2-f468-11e7-983e-001e67edf35d
rpc.py destroy_lvol_store -l lvs
Lvols
要在現有lvol存儲上創建lvol,用戶應使用construct_lvol_bdev
RPC命令。每個創建的lvol都將由新的bdev表示。
示例命令
rpc.py construct_lvol_bdev lvol1 25 -l lvs
rpc.py construct_lvol_bdev lvol2 25 -u 330a6ab2-f468-11e7-983e-001e67edf35d
Passthru
SPDK Passthru虛擬塊設備模塊用作如何編寫虛擬塊設備模塊的示例。它實現了vbdev模塊所需的功能,並演示了一些其他基本功能,例如每個I / O上下文的使用。
示例命令
rpc.py construct_passthru_bdev -b aio -p pt
rpc.py delete_passthru_bdev pt
Pmem
SPDK pmem bdev驅動程序使用pmemblk池作為塊I / O操作的目標。有關Pmem內存的詳細信息,請參閱http://pmem.io網站上的PMDK文檔。首先,用戶需要配置SPDK以包含PMDK支持:
configure --with-pmdk
要創建用於SPDK用戶的pmemblk池,應使用create_pmem_pool
RPC命令。
示例命令
rpc.py create_pmem_pool /path/to/pmem_pool 25 4096
要獲取有關已創建的pmem池文件的信息,用戶可以使用pmem_pool_info
RPC命令。
示例命令
rpc.py pmem_pool_info /path/to/pmem_pool
要刪除pmem池文件,用戶可以使用delete_pmem_pool
RPC命令。
示例命令
rpc.py delete_pmem_pool /path/to/pmem_pool
要基於pmemblk池文件創建bdev,用戶應使用construct_pmem_bdev
RPC命令。
示例命令
rpc.py construct_pmem_bdev /path/to/pmem_pool -n pmem
要刪除塊設備表示,請使用delete_pmem_bdev命令。
rpc.py delete_pmem_bdev pmem
Virtio Block
Virtio-Block驅動程序允許從Virtio-Block設備創建SPDK bdev。
以下命令創建一個Virtio-Block設備VirtioBlk0
,該設備以/tmp/vhost.0
SPDK vhost Target直接公開的vhost-user套接字命名。optional vq-count
和vq-size
params指定要使用的請求隊列數和隊列深度。
rpc.py construct_virtio_dev --dev-type blk --trtype user --traddr /tmp/vhost.0 --vq-count 2 --vq-size 512 VirtioBlk0
該驅動程序也可以在基於QEMU的VM中使用。以下命令創建一個名為VirtioBlk0
Virtio PCI設備的Virtio Block設備0000:00:01.0
。將從PCI配置空間自動讀取整個配置。它將反映傳遞給QEMU的vhost-user-scsi-pci設備的所有參數。
rpc.py construct_virtio_dev --dev-type blk --trtype pci --traddr 0000:01:00.0 VirtioBlk1
可以使用以下命令刪除Virtio-Block設備
rpc.py remove_virtio_bdev VirtioBlk0
Virtio SCSI
Virtio-SCSI驅動程序允許從Virtio-SCSI LUN創建SPDK塊設備。
Virtio-SCSI bdev的構造方式與Virtio-Block的構造方式相同。
rpc.py construct_virtio_dev --dev-type scsi --trtype user --traddr /tmp/vhost.0 --vq-count 2 --vq-size 512 VirtioScsi0
rpc.py construct_virtio_dev --dev-type scsi --trtype pci --traddr 0000:01:00.0 VirtioScsi0
每個Virtio-SCSI設備最多可以導出64個名為VirtioScsi0t0~VirtioScsi0t63的塊設備,每個SCSI設備一個LUN(LUN0)。以上2個命令將輸出所有暴露的bdev的名稱。
可以使用以下命令刪除Virtio-SCSI設備
rpc.py remove_virtio_bdev VirtioScsi0
刪除Virtio-SCSI設備將破壞其所有bdev。