天天看點

如何用 ndctl/ipmctl 管理工具 配置不同通路模式的pmem裝置

文章目錄

  • ​​1 PMEM 底層架構​​
  • ​​2 PMEM 邏輯架構​​
  • ​​3 ipmctl 建立 不同模式的 region​​
  • ​​3.1 安裝​​
  • ​​3.2 建立AppDirect mode的region​​
  • ​​3.3 建立 Memory Mode模式​​
  • ​​3.4 建立 混合模式​​
  • ​​3.5 檢視建立的結果​​
  • ​​4 ndctl 建立不同類型的 namespaces​​
  • ​​4.1 安裝​​
  • ​​4.2 建立/删除 一個任意類型的namespace​​
  • ​​4.3 指定類型 建立 namespaces​​
  • ​​4.4 變更已有namespace 類型​​
  • ​​5 namespace 的應用​​
  • ​​6 fio測試 fsdax 和 devdax​​
  • ​​7 參考​​

之前總結過一篇文章來總體介紹optane 持久記憶體 的架構以及其 程式設計模式

​​Intel Optane 持久記憶體概覽​​,這裡主要是記錄一下針對Optane 持久記憶體 管理工具的使用方式,通過這一些工具的使用能夠更為清晰得了解NVM(pmem) 的底層架構。

下文中提到的建立指令都是在 centos上進行的,不過ipmctl/ndctl/fio 這種基礎指令使用方式都是一樣的,可能就是安裝這一些工具的指令和其他的系統有一些差異。

1 PMEM 底層架構

PMEM 的存儲媒體是 3D Xpoint ,其底層存儲單元是PCM(phase change memory 即相變記憶體),這也是pmem 實體存儲和傳統的 NAND SSD最大的差異。但其和Optane NVMe SSD 最大的差異則是實體接口的不同,一個是PCIe接口(nvme ssd),一個是DIMM 接口(pmem)。 關于 NAND和3D XPoint 的實體差異可以通過​​從NMOS 和 PCM 底層存儲單元 來看NAND和3D XPoint的本質差別​​ 來了解一下。

那我們先看看 PMEM 的底層實體形态,這是我們的NUMA 下的cpu和記憶體插槽的分布。

如何用 ndctl/ipmctl 管理工具 配置不同通路模式的pmem裝置

其中藍色區域是DRAM 插槽,黑色插槽可以插PMEM 存儲媒體。

需要注意的是:

  1. 對于每一個CPU而言,PMEM 媒體應該插在每組(一藍一黑兩個算一組)靠近CPU的那一個槽中,即黑色的插槽;另一個槽插入DRAM。
  2. 使用App Direct Mode 的時候每組槽中的PMEM 可以不搭配DRAM;使用Memory Mode 的時候,每組槽中的PMEM必須搭配DRAM,否則無法配置成MemoryMode 模式使用。
  3. 必須要確定每個CPU兩邊的 pmem 媒體個數相等;而不同組 CPU 各自的PMEM數量可以不同,造成的結果就是兩個region 顯示的容量不同。

檢視目前系統DRAM 和 pmem 的拓撲結構

# 需要root 使用者執行
$ ipmctl show -topology
 DimmID | MemoryType | Capacity | PhysicalID| DeviceLocator
================================================================================
 0x0001 | Logical Non-Volatile Device | 126.375 GiB | 0x0021 | DIMM 6
 0x0011 | Logical Non-Volatile Device | 126.375 GiB | 0x0023 | DIMM 4
 0x0101 | Logical Non-Volatile Device | 126.375 GiB | 0x0027 | DIMM 7
 0x0111 | Logical Non-Volatile Device | 126.375 GiB | 0x0029 | DIMM 9
 0x1001 | Logical Non-Volatile Device | 126.375 GiB | 0x002d | DIMM 18
 0x1011 | Logical Non-Volatile Device | 126.375 GiB | 0x002f | DIMM 16
 0x1101 | Logical Non-Volatile Device | 126.375 GiB | 0x0033 | DIMM 19
 0x1111 | Logical Non-Volatile Device | 126.375 GiB | 0x0035 | DIMM 21
 N/A | DDR4 | 32.000 GiB | 0x0020 | DIMM 5
 N/A | DDR4 | 32.000 GiB | 0x0022 | DIMM 3
 N/A | DDR4 | 32.000 GiB | 0x0024 | DIMM 1
 N/A | DDR4 | 32.000 GiB | 0x0026 | DIMM 8
 N/A | DDR4 | 32.000 GiB | 0x0028 | DIMM 10
 N/A | DDR4 | 32.000 GiB | 0x002a | DIMM 12
 N/A | DDR4 | 32.000 GiB | 0x002c | DIMM 17
 N/A | DDR4 | 32.000 GiB | 0x002e | DIMM 15
 N/A | DDR4 | 32.000 GiB | 0x0030 | DIMM 13
 N/A | DDR4 | 32.000 GiB | 0x0032 | DIMM 20
 N/A | DDR4 | 32.000 GiB | 0x0034 | DIMM 22
 N/A | DDR4 | 32.000 GiB | 0x0036 | DIMM 24      

2 PMEM 邏輯架構

這裡介紹兩種 用于組織插在DIMM 插槽之上的邏輯分離存儲形态 ​

​region​

​​ 和 ​

​namespace​

​。

  • region : 用來組織pmem module的邏輯概念。一個region 中可以有一個或者多個pmem module(插在DIMM 上的pmem 存儲媒體)。目前支援的region 模式有兩種: interleave 和 non-interleave 的;其中interleave 模式是一個region 可以跨目前CPU的多個 DIMM,non-interleave 模式則是一個region 隻能在一個DIMM 上。
  • namespace: 是一段 on pmem 的 可連續尋址的位址範圍,類似于硬碟分區 或者 SCSI的邏輯單元(LUN) 或者 NVMe 的namespace。隻有在 建立的region 模式是 AppDirect 模式時才能在region 上建立namespace。

除了以上兩個主要的 對pmem 操作的邏輯分區之外,還有幾個概念需要了解:

  • Label : 每一個pmem module(pmem 存儲媒體) 都包涵一個 Label Storage Area(LBA) 區域,用來存儲namespace 的中繼資料配置。這樣,就可以在region 上建立不同類型的namespace 來支援針對pmem 的不同通路模式。
  • DAX:Direct Access。pmem 在AppDirect 模式下 通過namespace 建立的 不同類型的裝置可以為使用者提供 device access 以及 fs access的通路模式。在fs access 下 通過支援DAX 模式的檔案系統(xfs, ext4, on windows ntfs)來 最大程度得縮短通路pmem的路徑,通路的過程都是通過mmap 來進行的,能夠by-pass page-cache, i/o subsystem 以及 中斷和上下文切換。

下面是 non-interleaved regions 和 interleaved region 以及 on interleave region下的namespaces。

如何用 ndctl/ipmctl 管理工具 配置不同通路模式的pmem裝置

關于pmem 程式設計架構形态如下:

如何用 ndctl/ipmctl 管理工具 配置不同通路模式的pmem裝置

其中namespace 支援的四種模式 可以比對到上面針對 NVM-DIMMS 的通路形态中了:

  1. ​raw​

    ​: 就是一個記憶體盤的形态來直接通路,不支援DAX 模式的通路。
  2. ​sector​

    ​: 可以作為一個傳統的塊裝置 以及 on 塊裝置的檔案系統,且這個檔案系統不限制類型(任意檔案系,不需要dax支援)。可以允許按位元組通路,但是不能保證通路的原子性。
  3. ​fsdax​

    ​: 需要 pmem-aware filter system支援,即支援dax 挂載的檔案系統,這樣該namespace 可以通過标準檔案接口讀寫 ,同時也支援 通過pmdk 來通路。這個namespace 類型 是大多數的appdirect 模式下的持久記憶體使用方式。
  4. ​devdax​

    ​: 允許通過 mmap 直接将指定容量的 pmem 媒體映射到記憶體進行通路,這個devdax 模式的namespace 被建立出來之後不能像其他的塊裝置一樣建立dax檔案系統,它被映射出來之後是一個字元裝置形态(/dev/dax3.0 這種)。這種模式一般用作虛拟機,RDMA 以及 大頁映射。

到此,我們大體就清楚了PMEM 的邏輯架構 ,如何通過 邏輯 region 組織實體上的 DIMMS,以及如何在邏輯region之上建構資料分離存儲的namespaces。

接下來我們看看如果通過 pmem的 management tools 來組合這一些邏輯架構,建構豐富的pmem 使用形态。

3 ipmctl 建立 不同模式的 region

如果你的環境中已經有了pmem裝置(直接可用的檔案系統形态的pmem),可以直接跳過這一個工具的介紹,看下一個 ​

​ndctl​

​工具。

3.1 安裝

這個工具是建構pmem region的底層工具,建議安裝的時候讓其版本在​

​2.x​

​​ 及以上。

直接源碼編譯安裝即可:

git clone https://github.com/pmem/ndctl.git
cd ndctl
./autogen.sh
./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
make
make check
sudo make install      

安裝完成之後記得更新一下​

​PATH​

​​,否則指令行會找不到這個工具​

​export PATH=$PATH:/usr/local/bin​

​。

需要注意一個問題,就是如果你的ipmctl 最開始的版本比較低,可能會導緻最後建立的interleaved 模式的 region 無法建立混合模式的namespaces,這個issue 解決可以參考 ​​https://github.com/pmem/ndctl/issues/181​​。

關于ipmctl 工具的使用都需要在root 模式下執行

3.2 建立AppDirect mode的region

  1. 檢視目前已有mode
# ipmctl show -memoryresources
 MemoryType | DDR | PMemModule | Total
==========================================================
Volatile | 384.000 GiB | 0.000 GiB | 384.000 GiB
AppDirect | - | 1008.000 GiB | 1008.000 GiB
Cache | 0.000 GiB | - | 0.000 GiB
Inaccessible | 0.000 GiB | 3.377 GiB | 3.377 GiB
Physical | 384.000 GiB | 1011.377 GiB | 1395.377 GiB      

上面這個是AppDirectmode

  1. 建立AppDirect mode,這個指令會将目前的所有容量預設建立出interleaved mode的 region
# ipmctl create -goal PersistentMemoryType=AppDirect 
The following configuration will be applied:
 SocketID | DimmID | MemorySize | AppDirect1Size | AppDirect2Size
==================================================================
 0x0000 | 0x0001 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0000 | 0x0011 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0000 | 0x0101 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0000 | 0x0111 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0001 | 0x1001 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0001 | 0x1011 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0001 | 0x1101 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0001 | 0x1111 | 0.000 GiB | 126.000 GiB | 0.000 GiB
Do you want to continue? [y/n] y
Created following region configuration goal
 SocketID | DimmID | MemorySize | AppDirect1Size | AppDirect2Size
==================================================================
 0x0000 | 0x0001 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0000 | 0x0011 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0000 | 0x0101 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0000 | 0x0111 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0001 | 0x1001 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0001 | 0x1011 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0001 | 0x1101 | 0.000 GiB | 126.000 GiB | 0.000 GiB
 0x0001 | 0x1111 | 0.000 GiB | 126.000 GiB | 0.000 GiB
A reboot is required to process new memory allocation goals.
# reboot -n      

如果 想建立​

​non-interleaved​

​​ 模式的region,則可以執行指令:

​​

​ipmctl create -goal PersistentMemoryType=AppDirectNotInterleaved​

3.3 建立 Memory Mode模式

其中 ​

​MemoryMode​

​ 是一個百分比,如果是100的話則表示目前所有的pmem module 容量都會作為memory mode。

# ipmctl create -goal MemoryMode=100
# reboot      

重新開機之後,檢視​

​free -h​

​ 時能夠看到記憶體的容量已經加上了所有的 pmem module 的容量了

3.4 建立 混合模式

建立記憶體模式的時候 有一個參數 ​

​MemoryMode​

​​ 用來指定百分比,顯而易見 我們可以在一個機器上讓一部分的容量作為AppDirect 模式。

比如配置 50% 的容量為 memory mode 即可

# ipmctl create -goal MemoryMode=50      

以上過程中如果想要清理所有的 config,可以通過 ​

​ipmctl delete –goal​

​ 。

3.5 檢視建立的結果

  1. 檢視 goal ​

    ​ipmctl show -goal​

  2. 檢視regions ​

    ​ipmctl show -region​

  3. 檢視記憶體資源情況 ​

    ​ipmctl show -memoryresources​

  4. 檢視 dimms 分布 ​

    ​ipmctl show -dimms​

4 ndctl 建立不同類型的 namespaces

ndctl 的建立/删除/更新 namespace 需要root權限,檢視namepace 資訊則不需要root

4.1 安裝

ndctl 的安裝則不是很友善,如果系統庫不全的話可能遇到的問題會比較多,我将我的安裝完整過程貼下來:

  1. 前置庫安裝
sudo yum install autoconf pkg-config libndctl-devel libdaxctl-devel pandoc -y      
  1. 安裝過程
git clone https://github.com/pmem/ndctl.git
cd ndctl
git checkout v71 # 目前的最新版本

./autogen.sh
  Activated pre-commit hook.
  GIT_VERSION = 71
  sh: aclocal: command not found
  autoreconf: aclocal failed with exit status: 127 # 執行失敗
----------------------------------------------------

# 解決
sudo yum install automake libtool -y
autoreconf -ivf

# 執行成功
$ ./autogen.sh
----------------------------------------------------------------
Initialized build system. For a common configuration please run:
----------------------------------------------------------------
./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64

# 執行./configure 
./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
...
checking for a sed that does not truncate output... (cached) /usr/bin/sed
checking for asciidoctor... missing
configure: error: asciidoctor needed to build documentation # 執行失敗
----------------------------------------------------

# 解決
sudo yum install asciidoctor -y

# 重新執行 ./configure
./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
...
checking for KMOD... no
configure: error: Package requirements (libkmod) were not met:

No package 'libkmod' found

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix # 執行失敗
----------------------------------------------------

#解決
sudo yum install kmod kmod-devel -y

# 再次重新執行 ./configure
./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
...
configure: error: Package requirements (uuid) were not met:

No package 'uuid' found #執行失敗
----------------------------------------------------

#解決
sudo yum install libuuid-devel json-c-devel -y

# 執行./configure 成功,生成 Makefile
./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
# 安裝ndctl
make && sudo make install      

4.2 建立/删除 一個任意類型的namespace

  1. 檢視已有的namespaces ​

    ​ndctl list --namespaces --regions​

    ​ 能夠展示所有建立好的可用的 namespace 以及其所屬的 region資訊完整列印出來。
  2. 建立一個namespace,如果不指定namespace 類型的話預設建立的是raw 類型
ndctl create-namespace --force      
  1. 删除一個namespace 的話 可以通過 ​

    ​ndctl destroy-namespace namespace1.0 --force​

    ​​ 或者 不指定具體的某一個namespace,直接​

    ​--all​

    ​ 即可删除所有的namespaces,需要注意的是删除namespace 會清理掉目前namespace的所有資料。

4.3 指定類型 建立 namespaces

  1. 建立一個​

    ​fsdax​

    ​ 類型的namespace
ndctl create-namespace --mode=fsdax --size=100G --region=region0 --force      

指定在region0 上建立一個100G容量的 fsdax 模式namespace,建立成功則可以在​

​lsblk​

​​ 指令下看到這個塊裝置​

​/dev/pmem0​

​​。

除了以上參數,還可以指定一個比較重要的配置​​

​--map=dev​

​​或者​

​--map=mem​

​​,儲存目前namespace 的中繼資料資訊,大概是每4k 需要64B的存儲。​

​dev​

​​和​

​mem​

​ 分别制定的是将這部分中繼資料存放在pmem裝置上 或者 記憶體中。

  1. 上一條指令的基礎上 在​

    ​region0​

    ​​ 建立一個​

    ​devdax​

    ​ 模式的namespace
ndctl create-namespace --mode=devdax --size=100G --region=region0 --force      

建立好之後能​

​ls -l /dev/dax1.0​

​看到這個裝置,它是一個字元裝置。

如果這一步失敗,可以根據這個 issue 嘗試解決:​​https://github.com/pmem/ndctl/issues/181​​

這樣建立出來的namespace 對應的 region 以及 dimm 關系圖如下:

如何用 ndctl/ipmctl 管理工具 配置不同通路模式的pmem裝置

4.4 變更已有namespace 類型

變更namespace1.0 的配置,從fsdax 模式變更為 devdax模式

​​

​ndctl create-namespace --mode=devdax --size=100G --reconfig=namespace1.0​

​。

注意:

reconfig 的流程會

  1. 先從已有的namespace中讀取 中繼資料資訊
  2. 然後删除已有的namespace,這一步會清理所有的資料
  3. 根據reconfig 的配置重新建立namespace

更多的建立資訊,可以參考​​https://pmem.io/ndctl/ndctl-create-namespace.html​​

5 namespace 的應用

這裡就很簡單了,主要是針對fsdax 裝置的使用

通過fsdax 模式建立出來的 一個塊裝置可以直接格式化成dax 支援的檔案系統 并挂載:

sudo mkfs.xfs -f /dev/pmem0
sudo mount -o dax /dev/pmem0 /mnt/pmem0      

此時即可使用檔案接口進行讀寫。

6 fio測試 fsdax 和 devdax

建議測試的​

​fio​

​​ 版本直接使用最新的​

​3.17​

​,這樣能夠使用比較新的ioengine (libpmem/dev-dax)

  1. 測試fsdax
以下綁定的numa 不一定準确,可以通過​

​lscpu​

​ 檢視numa的cpu,随便綁定一個,哪個性能好 則目前namespace 的region 就在哪個 numa上。
[global]
ioengine=libpmem #pmem引擎
direct=1
norandommap=1
randrepeat=0
runtime=60
time_based
size=1G
directory=./fio
group_reporting
[read256B-rand]
bs=256B
rw=randread
numjobs=32
iodepth=4 
cpus_allowed=0-15,16-31 #綁定numa      
  1. ​ndctl list --regions --namespaces​

    ​​ 檢視目前的 ​

    ​/dev/pmem0​

    ​ 屬于哪一個region
  2. ​ipmctl show -region​

    ​ 檢視目前的region 屬于哪一個socket,0 則是numa node0, 1 則是numa node1等
  1. 測試devdax,不支援​

    ​direct​

    ​開啟,直接通路的字元裝置
[global]
ioengine=dev-dax
direct=0
norandommap=1
randrepeat=0
runtime=60
time_based
size=1G
filename=/dev/dax1.0 #直接指定filename 為devdax模式的字元裝置即可
group_reporting
[read256B-rand]
bs=256B
rw=randread
numjobs=32
iodepth=4 
cpus_allowed=0-15,16-31 #綁定numa      

7 參考

  1. ​​Introduction to Persistent Memory Configuration and Analysis Tools​​
  2. ​​Persistent Memory Provisioning Introduction​​
  3. ​​support virtual persistent memory​​
  4. ​​https://pmem.io/ndctl/​​
  5. ​​https://nvdimm.wiki.kernel.org/​​
  6. ​​NDCTL Introduction​​
  7. ​​PMEM 主機安裝環境詳解​​

繼續閱讀