Linuxの不揮発メモリ(NVDIMM対応について(2019年版 補足編)


#はじめに

（この記事は[Fujitsu Advent Calendar 2019](https://qiita.com/advent-calendar/2019/fujitsu) 24日目の記事です。なお、記事は個人の見解であり、組織を代表するものではありません。）

というわけで、今年もNVDIMMこと不揮発メモリの話を書くことにしました。補足編となっているのは、今年はすでに12月の講演で最新状況をほとんど話してしまっていて、その講演の時間内に収められなかった小ネタを補足としてするつもりだからです。

正直言うと、2019年は業務の都合上NVDIMMのお仕事はほとんど何もやっていなかったんです。しかし、過去3回にわたってひたすらNVDIMMの話を書いているせいか、最近はすっかりNVDIMMの人として見られるようになっている気がします。そのおかげで過去の記事をご覧になった大学の先生などから講演のお声がかかるようになってきたというわけです。ありがたいことです。 Outputを外に出すとそれが自分にいい方向で跳ね返ってくるというのを身をもって体験していて、中々感慨深いものがあります。

* 2019/3月 Big Data Infra研究会で講演
* 2019/12月 情報処理学会の[Comsys 2019](http://www.ipsj.or.jp/sig/os/index.php?ComSys2019)にて講演

以下は、前者が3月の時の資料、後者が12月の情報処理学会 Comsys 2019の資料です。12月の時は後半の最新状況が更新されています。
[不揮発メモリ(NVDIMM)とLinuxの対応動向について](https://www.slideshare.net/ygotokernel/nvdimmlinux-137104084)
[不揮発メモリ(NVDIMM)とLinuxの対応動向について (for comsys 2019 ver.)](https://www.slideshare.net/ygotokernel/nvdimmlinuxfor-comsys-2019-ver)

というわけで、今年の最新動向についてはこの記事より前に、まずは上記（特に12月の方の資料）をご参照ください。
ここでは、12月の講演の45分の時間中に入りきらなかった話や気が付いてなかった点について補足しようと思います。

なお不揮発メモリについては、今年はNAOMASA MATSUBAYASHIさんによる解説資料
[電源を切っても消えないメモリとの付き合い方](https://speakerdeck.com/fadis/dian-yuan-woqie-tutemoxiao-enaimemoritofalsefu-kihe-ifang)
が資料も公開されています。PMDKのlibpmemobjの使い方などは、私の解説より詳しいのでこちらも参照するとよいでしょう。

# 1.不揮発メモリを揮発メモリとして使うカーネルの機能

Dave Hansenさんによって、NVDIMMを容量の大きなRAMとして使うためのkernelの機能が開発されました。
https://lkml.org/lkml/2019/1/24/1346

NVDIMMにはもともと癖のある不揮発な性質よりも、不揮発メモリの大容量性のみに着目して従来のRAMと同じように不揮発メモリを使いたいという期待もありました。このため、Intelはこれまで以下の方法を提供してきました。
##### A) Memory Mode
ハード／ファームの設定により、RAMをcacheにしてNVDIMMの領域を通常のMemory領域に見せるというModeです。（これに対して、NVDIMMを本当に不揮発メモリに見せるModeはApp Direct Modeと呼びます）。

Memory Modeではソフトの変更を一切行わずに済むのが長所です。しかし、RAMをキャッシュとして使ってしまうので、RAMの容量はメモリサイズとしては見えなくなってしまい、図のようにNVDIMMの容量がそのままメモリサイズとなります。また、キャッシュであるのでキャッシュミスしたときのレイテンシーの変化などはソフト側で予測できず、またコントロールできないのも欠点です。

![Memory_mode.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101351/8e8e2e7e-23aa-61b1-c801-e856a5966204.jpeg)



##### B) libraryによってNVDIMMの揮発メモリのように使う
（元）PMDKのlibvmemのように、ライブラリレベルでDAXとしてわりあてたNVDIMMの領域を揮発メモリ的に使う方法です。当然、これらのライブラリを使わないと揮発メモリとしては使えないので、ミドルウェアやアプリがこのライブラリに対応している必要があります。このため、これを使うのはちょっと面倒です。


そこで登場したのがDaveさんのパッチです。
##### C) kernelレイヤでNVDIMMを揮発メモリとして見せてくれる

これによると、Device DAXとしてフォーマットした領域をいったん切り離して、それをMemory hotaddしてRAMとして見せるようにしているようです。これによりNVDIMMがユーザからは少し遅いRAMとして見えるようになります。

![NVDIMM_volatile_patch.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101351/28e8d451-bdea-cb82-a3d1-dadb6a08f153.jpeg)

この方式の長所は以下があげられます。
* Memory Modeと違って、RAMとNVDIMMの両方が通常の揮発メモリとして利用できるため、揮発メモリとして使えるメモリの容量がMemory Modeより多い。
* NVDIMMはNUMAの別ノードとして見えるので、numactlなどを使って、RAMとNVDIMMのどちらを使うか切り替えられる。更新頻度が高いデータはRAMの側に、更新頻度が低いけど大きなデータはNVDIMM側に置くといった使い方ができる。

とくに後者の特徴は、NVDIMMの耐久性を気にする人にとってはありがたい機能といえるでしょう。

この一連のメールの最後のパッチによると、使い方はいったんdevice DAXの領域を作って、以下のように指定すると利用できるようになるようです。

```
To make this work, management software must remove the device from
being controlled by the "Device DAX" infrastructure:

	echo -n dax0.0 > /sys/bus/dax/drivers/device_dax/remove_id
	echo -n dax0.0 > /sys/bus/dax/drivers/device_dax/unbind

and then bind it to this new driver:

	echo -n dax0.0 > /sys/bus/dax/drivers/kmem/new_id
	echo -n dax0.0 > /sys/bus/dax/drivers/kmem/bind
```

#2. PMDKの揮発メモリライブラリがPMDKから外れた

ところで、上記のPMDKの揮発メモリライブラリのところで、「（元）」という記載に気が付いた方はどれくらいいるでしょうか？ PMDKのlibvmemとlibvmemallocは、結局PMDKから外れて別のレポジトリになったようです。以前からIntelはこのlibvmemの利用用途では「memkindを使ってほしい」という言い方をしていましたが、とうとうPMDK本体から外されてしまったようです。

https://pmem.io/2019/10/31/vmem-split.html

Windowsではmemkindは対応していないようなので、まだlibvmemの存在には意味があります。が、Linuxでは少なくともlibvmemよりはmemkindを使った方が（あるいは上記のkernelの機能を使う方が）よさそうです。

# 3. dm-writecache

Device mapperのレイヤでデータをNVDIMMを使ってキャッシュする機能がkernel 4.18でマージされたようです。kernelにはすでにv3.10ぐらいの頃からdm-cacheというSSDなどを使ってキャッシュする機能がありましたが、dm-writecacheでは、NVMeのような高速SSDのほかに、NVDIMMにキャッシュできるのが特徴といえるでしょう。NVDIMMのユースケースとしては遅い記憶媒体をキャッシュするというわりと古典的な使い方かもしれません。しかし、bttのようなブロック単位のデータ保証ではなく、CPUキャッシュ単位での制御を行っているなどしているようで、NVDIMMにより適した制御を行っているようなので、dm-cacheよりは高速性が期待できます。

以下にHuaisheng Yeさんの発表資料がありますから、それを参照するのが概要を知るにはちょうど良いでしょう。図も多くてどんなものかはある程度分かるはずです。
[Dm-writecache: a New Type Low Latency Writecahe Based on NVDIMM](https://github.com/ChinaLinuxKernel/CLK2019/blob/master/clk2019-dm-writecache-04.pdf)

これまでのdm-cacheでは、標準ではwrite throughになっていてwrite backはオプションのようですが、それに対してdm-writecacheではwrite backのようです（write throughはないという記事も見かけました）。資料中の図によると、readはキャッシュせず基本的にHDDに直接読みに行くようです。
また、writeでcacheしたデータだけはreadのときにhitするとそちらを読むというようにも見えますが、それが正しいとするとreadは既存のkernelのpage cacheの仕組みに任せてしまって、書き込みのデータ保証をできるだけ早くするという、非常に割り切った作りだといえるでしょう。

資料によると、以下のように設定するようです

```
# lvcreate -n hdd_wc -L 4G vg /dev/sda1 (キャッシュされるデバイス）
# lvcreate -n cache_wc -L 1G vg /dev/pmem0 (Filesystem DAXとして設定したNVDIMMのnamespaceのデバイス名)
# lvchange -a n vg/cache_wc
# lvconvert --type writecache --cachevol cache_wc vg/hdd_wc
```

また、block deviceとして使うsector modeのnamespaceではなく、Filesystem DAXのnamespaceを使うことができるため、NVDIMMにより最適なアクセスができるようにしているようです。資料にはNVDIMMをsectorモードにしてdm-cacheで使った時に対してFilesystem-DAXモードにして、dm-writecacheで使った時の性能比較や、CephのOSDとしてこれを適用してみた例も載っています。


時間があれば、ちょっとこれも触ってみて検証してみたいところですね。

# まとめ

Comsys 2019で話しきれなかったことについて少しですが補足しました。本当はエミュレーション環境などでちょっと試してみたかったのですが、今回は時間切れです。また時間ができた時にそれぞれ試してみたいと思います。

まだまだ媒体が手に入りやすいとは言いづらいですが、LinuxはNVDIMMのために毎年少しずつ進化し続けています。
2020年の動向にも期待しましょう。