Jump to contentJump to page navigation: previous page [access key p]/next page [access key n]
適用先 openSUSE Leap 15.6

19 永続型メモリ Edit source

概要

本章では、 1 枚以上の NVDIMM から構成される不揮発性メインメモリ (永続型メモリ と呼ばれる場合もあります) を openSUSE Leap で使用するための情報を記述しています。

19.1 概要 Edit source

永続型メモリは新しいタイプのコンピュータストレージで、 DRAM (ダイナミック RAM) の高速性とバイト単位でのアクセス機能を維持したまま、ソリッドステートドライブ (SSD) の永続性を付加した仕組みを指します。

SUSE では現在、 AMD64/Intel 64 および POWER の各アーキテクチャで動作する openSUSE Leap で、永続型メモリの使用をサポートしています。

一般的な RAM と同様に、永続型メモリはメインボードのメモリスロットに直接差し込む形態で設置を行います。つまりこれは、 DIMM と呼ばれる通常型の RAM と物理的に全く同じ構造であることを意味しています。このような永続型メモリを NVDIMM (不揮発型 DIMM) と呼ぶ場合もあります。

ただし RAM とは異なり、永続型メモリは SSD のようなフラッシュメモリとも類似しています。 SSD も永続型メモリも半導体メモリではありますが、いずれも揮発性がありません。つまり、システムの電源を落としたり、再起動したりしても、中に書き込まれた内容はそのまま保持されるということを意味しています。またどちらの媒体も、書き込みのほうが読み込みよりも遅く、書き換え回数にも制限が存在しています。このほか SSD と同様に、永続型メモリはセクタ単位でのアクセスにも対応し、アプリケーション側からの要件に合わせることができるようになっています。

また、不揮発型メモリは Intel 3D XPoint という特殊なフラッシュメモリを搭載したものや、 NAND フラッシュと DRAM の両方を搭載したものなど、様々な構成で提供されています。このような新しい不揮発型メモリは現在も開発が続けられていて、様々な販売元がさらに性能を強化し耐久性を高めるよう新製品が作り続けられています。

このような永続型メモリの技術は未だ発展途上の段階にあるため、販売元によって様々な制限が存在する場合があります。そのため本章では、一般論のみを説明しています。

永続型メモリは DRAM と比べると 10 倍程度遅い仕組みですが、フラッシュメモリと比較すると 1000 倍程度高速です。フラッシュメモリは一般にセクタ単位で消去して書き換えを行いますが、永続型メモリは 1 バイト単位で書き換えが可能です。また、書き換え回数には制限があるものの、ほとんどの永続型メモリは 100 万回程度の書き換えに対応しています。これはフラッシュメモリの 1000 回程度に比べるとずっと大きな値です。

このようなことから、下記の 2 つの結果をもたらします:

  • 現在の技術では、永続型メモリのみでシステムを動作させることはできないため、完全な永続性は提供できません。通常型の RAM と NVDIMM の両方を組み合わせて使用することになります。オペレーティングシステムやアプリケーションは通常型の RAM 内で実行し、 NVDIMM は高速な補助型ストレージとして使用することになります。

  • 永続型メモリは販売元によって様々な性能の差異や特徴があることから、プログラマ側はサーバ内の NVDIMM のハードウエア特性を知っておく必要があります。これには NVDIMM の容量のほか、使用しているメモリスロットの場所も含まれます。これによってハイパーバイザ用途での使用やホストマシン間のソフトウエア移行など、様々な箇所の性能に影響があるためです。

この新しいストレージサブシステムは、 ACPI のバージョン 6 標準で規定されています。ただし、 libnvdimm は標準化される前の NVDIMM のみに対応しているため、その仕組みでのみ使用できることに注意してください。

ヒント
ヒント: Intel Optane DC 永続型メモリ

Intel Optane DIMM メモリは、下記の固有モードで使用することができます:

  • App Direct モード: Intel Optane メモリを高速な永続型ストレージとして使用するモードで、 SSD や NVMe デバイスの代替として扱うことができます。このモードを指定すると、システムの電源が落ちてもデータは保持されるようになります。

  • Memory モード: Intel Optane メモリを、 DRAM と比べて費用対効果の高い大容量メモリとして使用するモードです。このモードでは Optane DIMM の容量を生かして、個別の DIMM 内にアクセス頻度の高いデータをキャッシュとして保存します。ただし DRAM のみのシステムとは異なり、このモードはランダムアクセスの多い用途には向いておらず、性能が落ちてしまうことに注意してください。また、このモードを使用する場合は、アプリケーション側に Optane 固有の機能拡張を使用する必要があることにも注意してください。なお、このモードではシステムの電源が落とされると、データが失われます。

  • Mixed モード: Intel Optane メモリを内部で区分けして、上述の両方のモードを同時に使用します。

Intel Optane DC 永続型メモリに関する詳細は、 https://www.intel.com/content/dam/support/us/en/documents/memory-and-storage/data-center-persistent-mem/Intel-Optane-DC-Persistent-Memory-Quick-Start-Guide.pdf (英語) をお読みください。

19.2 用語 Edit source

リージョン

リージョン とは永続型メモリの中のブロックを意味する用語で、 1 つまたは複数の ネームスペース が含まれるものです。永続型メモリを使用する際には、まずネームスペースに割り当ててからアクセスを行います。

ネームスペース

永続型メモリ内の連続したアドレス領域を指す用語で、 NVM Express SSD におけるネームスペースや SCSI での Logical Unit (LUN) と同じような意味を持ちます。ネームスペースはサーバ内の /dev ディレクトリ内に個別のブロックデバイスとして提供されます。必要なアクセス方式によっても異なりますが、複数の NVDIMM からのストレージを組み合わせてネームスペースを大きなボリュームにしたり、小さなボリュームに分割したりすることもできます。

モード

それぞれのネームスペースには モード が設定されます。これはネームスペース内で有効化する NVDIMM の機能を意味するもので、同じ親リージョンを持つ兄弟姉妹間のネームスペースでは同じ型になるものの、異なるモードを設定することができます。ネームスペースのモードには下記のようなものがあります:

devdax

デバイス DAX と呼ばれるモードで、単一のキャラクタデバイスファイル ( /dev/daxX.Y ) を作成します。このモードの場合、ファイルシステムの作成は不要です。

fsdax

ファイルシステム DAX と呼ばれるモードで、何もモードを指定しない場合の既定値です。ext4XFS のファイルシステムを構築できるブロックデバイス ( /dev/pmemX [.Y] ) を作成します。

sector

チェックサムメタデータに対応していない古いファイルシステム向けの設定です。小さな起動ボリュームに最適な構成で、古いその他のオペレーティングシステムとの互換性もあります。

raw

ラベルやメタデータを持たない純粋なメモリディスクのモードです。 DAX には対応していません。古いその他のオペレーティングシステムとの互換性があります。

注記
注記

raw モードは SUSE ではサポート対象外となります。また、 raw ネームスペース内に作成したファイルシステムをマウントすることもできません。

それぞれのネームスペースやリージョンには が設定されます。この はネームスペースやリージョンに割り当てられた永続型メモリへのアクセス方式を設定するもので、ネームスペースは親となるリージョンと同じ型になります。型には 2 種類のものがあり、それぞれ 永続型メモリ (さらに 2 種類の設定形態があります) と ブロックモード (古い形式です) と呼ばれています。

永続型メモリ (PMEM)

PMEM ストレージは通常のメモリ (RAM) と同様に、 1 バイト単位のアクセス機能を提供します。 PMEM を使用することで、複数のインターリーブされた NVDIMM を単一のネームスペースにまとめて 1 つのデバイスとして使用することができます。

PMEM 型のネームスペースの設定には、 2 種類の形態があります。

DAX を使用する PMEM

PMEM 型のネームスペースに対してダイレクトアクセス (DAX) を設定すると、メモリへのアクセス時にカーネルのページキャッシュを使用せず、直接メディアにアクセスするようになります。ソフトウエア側では、ネームスペース内の任意の箇所を個別に読み書きできるようになります。

ブロック変換テーブル (BTT) を利用する PMEM

PMEM 型のネームスペースに対して BTT モードを設定すると、通常のメモリアクセスのようなバイト単位でのアクセスではなく、通常のディスクドライブと同様のセクタ単位でのアクセスを行うようになります。変換テーブルの仕組みにより、セクタ単位で一括アクセスします。

BTT の利点はデータ保護にあります。ストレージサブシステムでは、それぞれのセクタがメディアに全て書き込まれたかどうかを監視しますので、書き込み切れていない場合 (たとえば何らかの理由で書き込みが失敗した場合など) はセクタ全体を以前の状態に戻す処理を行いますので、中途半端な状態にならないように動作します。

これに加えて、 BTT ネームスペースへのアクセスはカーネル側でのキャッシュ対象となります。

ただし、 BTT ネームスペースの場合は DAX を利用できない欠点があることに注意してください。

ブロックモード (BLK)

ブロックモードでは、それぞれの NVDIMM を個別のデバイスとして割り当てます。このモードは古い方式であり、サポート対象外となります。

devdax 以外の全ての型では、通常のドライブと同様にファイルシステムを指定してフォーマットを行う必要があります。 openSUSE Leap では ext2 , ext4 , XFS の各ファイルシステムに対応しています。

直接アクセス (DAX)

DAX は永続型メモリを直接アクセスする方式で、 mmap システムコールなどを利用してプロセスのメモリ領域内に直接マッピングすることができます。

DIMM 物理アドレス (DPA)

特定の DIMM メモリ内のオフセット値として表現するメモリアドレスを意味します。 DIMM 内の最初のバイトを 0 とした値で表現します。

ラベル

NVDIMM 内に保存されたメタデータで、たとえばネームスペースの設定などが含まれます。 DSM を利用してアクセスすることができます。

デバイス固有メソッド (DSM)

NVDIMM 内のファームウエアにアクセスするための ACPI メソッドです。

19.3 用途 Edit source

19.3.1 DAX を使用する PMEM Edit source

この形態でのメモリアクセスはトランザクション処理に対して 安全ではありません 。電源障害やその他のシステム障害が発生した場合、ストレージ内に全てのデータが書き込まれていることを保証できない仕組みであるため、アプリケーション側でそれを保証できる場合にのみ使用してください。

19.3.1.1 1 バイト単位でアクセス可能な巨大ストレージとしての使用 Edit source

高速な巨大ストレージにバイト単位で直接アクセスできるアプリケーションを使用する場合は、プログラム側で mmap システムコールを利用して永続型メモリをアプリケーションのメモリ領域に展開して使用することができます。この場合、追加のシステムメモリは不要となります。

19.3.1.2 カーネルのページキャッシュの回避について Edit source

ページキャッシュ用のメモリを節約したい場合は、カーネルのページキャッシュを使用しないように設定するものとし、余ったメモリはアプリケーション側に割り当てるようにしてください。たとえば永続型メモリを仮想マシン (VM) のイメージ保存用に占有させるような場合がそれに該当します。ページキャッシュを使用しないように設定することで、ホスト内でのメモリ使用量を削減できますので、それによってホスト内でさらに多くの VM を動作させることができるようになります。

19.3.2 BTT を使用する PMEM Edit source

こちらは永続型メモリを高速なディスクプールとして構成する場合に便利な仕組みです。たとえば BTT を指定した PMEM 内にファイルシステムのジャーナルを配置すると、電源やその他の障害が発生した場合に信頼性を向上させることができます (詳しくは 19.5.3項 「BTT を利用した PMEM ネームスペースの作成」 をお読みください) 。

アプリケーション側からは高速な SSD デバイスに見えますので、通常のストレージデバイスと同じように扱うことができます。たとえば永続型メモリ内に LVM を構成したりすることもできます。

また BTT はセクタ単位での書き込みを行いますので、常に一貫性が保たれる利点もあります。アプリケーション側ではデータの信頼性確保に力を注ぐことなく処理することができます。メディアエラーが発生したような場合でも、標準のエラー報告チャンネルを介して通知が行われます。

19.4 永続型メモリを管理するためのツール Edit source

永続型メモリを管理するには、 ndctl パッケージをインストールします。このパッケージをインストールすると libndctl パッケージもインストールされますが、こちらは NVDIMM を設定するためのユーザスペース側ライブラリです。

これらのツールは libnvdimm ライブラリを介して動作しますが、このライブラリは下記 3 種類の NVDIMM に対応しています:

  • PMEM

  • BLK

  • PMEM と BLK の共存環境

ndctl にはさまざまなマニュアルページ (man) が含まれています。マニュアルページを表示するには、下記のコマンドを実行してください:

> ndctl help サブコマンド名

利用可能なサブコマンドの一覧を表示するには、下記のとおり実行してください:

> ndctl --list-cmds

利用可能なサブコマンドには、下記のようなものがあります:

version

NVDIMM サポートツールのバージョンを表示します。

enable-namespace

指定したネームスペースを使用できるように設定します。

disable-namespace

指定したネームスペースを使用できないように設定します。

create-namespace

指定したストレージデバイスから新しいネームスペースを作成します。

destroy-namespace

指定したネームスペースを削除します。

enable-region

指定したリージョンを使用できるように設定します。

disable-region

指定したリージョンを使用できないように設定します。

zero-labels

デバイス内のメタデータを消去します。

read-labels

指定したデバイスからメタデータを取得します。

list

利用可能なデバイスの一覧を表示します。

help

このツールの使用方法に関する情報を表示します。

19.5 永続型メモリの設定 Edit source

19.5.1 利用可能な NVDIMM ストレージの表示 Edit source

ndctl list コマンドを実行すると、システム内で利用可能な全ての NVDIMM を表示することができます。

下記の例では、システム内に 3 つの NVDIMM が存在していて、それらは単一で 3 チャンネルのインターリーブセットを構成しています。

# ndctl list --dimms

[
 {
  "dev":"nmem2",
  "id":"8089-00-0000-12325476"
 },
 {
  "dev":"nmem1",
  "id":"8089-00-0000-11325476"
 },
 {
  "dev":"nmem0",
  "id":"8089-00-0000-10325476"
 }
]

ndctl list に異なるパラメータを指定することで、利用可能なリージョンの一覧を表示することもできます。

注記
注記

リージョンは番号順に出力されない場合があります。

下記は 3 つの NVDIMM が搭載されているものの、 4 つのリージョンが設定されていることに注意してください。

# ndctl list --regions

[
 {
  "dev":"region1",
  "size":68182605824,
  "available_size":68182605824,
  "type":"blk"
 },
 {
  "dev":"region3",
  "size":202937204736,
  "available_size":202937204736,
  "type":"pmem",
  "iset_id":5903239628671731251
  },
  {
   "dev":"region0",
   "size":68182605824,
   "available_size":68182605824,
   "type":"blk"
  },
  {
   "dev":"region2",
   "size":68182605824,
   "available_size":68182605824,
   "type":"blk"
  }
]

領域には 2 種類の異なる形式が設定されています。一方は 3 つの BLK 型の 64 GB の領域として、もう一方は 3 つの NVDIMM を単一のボリュームとして利用できる、 PMEM 型の 189GB 領域です。

なお、上記の例では available_sizesize の値が同じになっていますが、これは現時点では領域を何も使用していないことを表します。

19.5.2 DAX を利用し単一の PMEM ネームスペースとして使用する設定 Edit source

最初の例では、 3 つの NVDIMM を単一の PMEM ネームスペースに統合し、これを直接アクセス (DAX) 型として設定します。

最初にやるべきことは、新しいネームスペースを作成することです。

# ndctl create-namespace --type=pmem --mode=fsdax --map=memory
{
 "dev":"namespace3.0",
 "mode":"memory",
 "size":199764213760,
 "uuid":"dc8ebb84-c564-4248-9e8d-e18543c39b69",
 "blockdev":"pmem3"
}

上記を実行すると /dev/pmem3 という DAX に対応したブロックデバイスが作成されます。デバイス名の 3 は親リージョンの番号 (region3) から受け継いだ値になります。

--map=memory オプションを指定すると、 NVDIMM 内の PMEM ストレージの一部を予約して ページ記述子 と呼ばれるカーネル内部データ構造を保存させることができます。これにより、新しい PMEM ネームスペースで O_DIRECT I/ORDMA のような機能を使用できるようになります。

カーネルのデータ構造を永続型メモリ内に予約することから、生成される PMEM ネームスペースは、親の PMEM リージョンより小さい容量になります。

次に、新しく作成したブロックデバイスがオペレーティングシステム側からアクセスできることを確認します:

# fdisk -l /dev/pmem3
Disk /dev/pmem3: 186 GiB, 199764213760 bytes, 390164480 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes

他のドライブと同様に、こちらもフォーマットを行う必要があります。下記の例では、 XFS でフォーマットしています:

# mkfs.xfs /dev/pmem3
meta-data=/dev/pmem3      isize=256    agcount=4, agsize=12192640 blks
         =                sectsz=4096  attr=2, projid32bit=1
         =                crc=0        finobt=0, sparse=0
data     =                bsize=4096   blocks=48770560, imaxpct=25
         =                sunit=0      swidth=0 blks
naming   =version 2       bsize=4096   ascii-ci=0 ftype=1
log      =internal log    bsize=4096   blocks=23813, version=2
         =                sectsz=4096  sunit=1 blks, lazy-count=1
realtime =none            extsz=4096   blocks=0, rtextents=0

次に、新しいドライブをディレクトリにマウントします:

# mount -o dax /dev/pmem3 /mnt/pmem3

あとは DAX に対応したデバイスとしてマウントできていることを確認します:

# mount | grep dax
/dev/pmem3 on /mnt/pmem3 type xfs (rw,relatime,attr2,dax,inode64,noquota)

上記までの作業で、 PMEM ネームスペースを XFS ファイルシステムでフォーマットし、 DAX でマウントすることができます。

このファイルシステム内のファイルに対して mmap() システムコールを使用することで、 NVDIMM 内の永続型メモリに直接辿り着くことのできる仮想アドレスを取得することができます。もちろんページキャッシュは迂回する形になります。

このファイルシステム内のファイルに対して fsyncmsync コールを実行すると、 NVDIMM 内に変更されたデータ全てを書き込んでいることが保証されます。これらのコールは、ユーザスペース側で mmap した内容のページを、プロセッサキャッシュからも排除して書き込みを保証します。

19.5.2.1 ネームスペースの削除 Edit source

同じストレージで別の種類のボリュームを作成したい場合は、あらかじめマウントを解除して PEM ストレージを削除しておく必要があります。

まずはマウントを解除します:

# umount /mnt/pmem3

続いてネームスペースを無効化します:

# ndctl disable-namespace namespace3.0
disabled 1 namespace

あとは削除するだけです:

# ndctl destroy-namespace namespace3.0
destroyed 1 namespace

19.5.3 BTT を利用した PMEM ネームスペースの作成 Edit source

BTT はセクタ単位での書き込み一貫性を提供する仕組みで、 ext4 や xfs のジャーナルのようにデータ保護を必要とする場合に適切な選択肢です。電源障害が発生したりした場合、ジャーナルは保護され復元可能な状態にならなければなりませんが、下記の例では BTT を利用した PMEM ネームスペースを作成して、ジャーナルをそこに配置する場合の手順を示しています。

# ndctl create-namespace --type=pmem --mode=sector
{
 "dev":"namespace3.0",
 "mode":"sector",
 "uuid":"51ab652d-7f20-44ea-b51d-5670454f8b9b",
 "sector_size":4096,
 "blockdev":"pmem3s"
}

次に新しいデバイスが存在していることを確認します:

# fdisk -l /dev/pmem3s
Disk /dev/pmem3s: 188.8 GiB, 202738135040 bytes, 49496615 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes

上述の手順で作成した DAX 対応の PMEM ネームスペースと同様に、この BTT 対応の PMEM ネームスペースは NVDIMM 内で利用可能な全てのストレージを使用しています。

注記
注記

デバイス名 ( /dev/pmem3s ) の末尾にある ssector (セクタ) の意味で、 BTT が設定されていることを名前から容易に判別できるようにしています。

作成されたボリュームは、上述の例と同じくフォーマットしてマウントすることができます。

ただし、ここで示した PMEM ネームスペースでは DAX を使用できません。その代わり、 BTT を利用して セクタ単位の書き込み保証 を提供します。それぞれのセクタへの書き込みは PMEM ブロックドライバを介して行われますが、この場合まず BTT は新しいセクタを書き込み用に確保します。 BTT は確保したセクタ内に書き込みが完了したことを確認したのち、内部マッピングを新しいセクタに書き換えて、アプリケーション側からアクセスできるようにします。この仕組みにより、処理中に電源障害が発生したような場合でも、書き込み前の古いデータを参照できるようになります。これにより、 "torn sectors" と呼ばれる中途半端に書き込まれたデータになることを防いでいます。

このように BTT が有効化された PMEM ネームスペースは、通常の標準ブロックデバイスと同様にファイルシステムを指定してフォーマットすることができます。 DAX は使用できませんが、そのブロックデバイス内のファイルに対して mmap を行うことでページキャッシュを使用することができます。

19.5.4 PMEM/BTT 内へのファイルシステムジャーナルの配置 Edit source

ファイルシステムのジャーナルを別のデバイスに配置する場合、元のファイルシステムと同じブロックサイズを使用しなければなりません。一般的には 4096 が最も使用されていますが、念のため下記のコマンドで確認してください:

# blockdev --getbsz /dev/sda3

下記の例では、 NVDIMM デバイス内に新しい ext4 ジャーナルを、 SATA デバイス内に新しい ext4 ファイルシステムをそれぞれ作成して、ファイルシステムとジャーナルを結びつけるまでの処理を行っています:

# mke2fs -b 4096 -O journal_dev /dev/pmem3s
# mkfs.ext4 -J device=/dev/pmem3s /dev/sda3

下記の例では SATA ドライブに新しい XFS ファイルシステムを、別の NVDIMM デバイス内にジャーナルを作成しています:

# mkfs.xfs -l logdev=/dev/pmem3s  /dev/sda3

オプションの指定方法に関する詳細は、 man 8 mkfs.ext4 およびman 8 mkfs.ext4 をお読みください。

19.6 さらなる情報 Edit source

本件に関するその他の情報は、それぞれ下記をお読みください (いずれも英語のみの提供となります):

  • Persistent Memory Wiki

    NVDIMM システムの設定手順やテストに関する情報、そして NVDIMM の有効化に関する個別の情報へのリンクがそれぞれ提供されています。このサイトは Linux 内での NVDIMM サポートとともに記述が進められています。

  • Persistent Memory Programming

    Linux やその他のオペレーティングシステムで、永続型メモリの設定方法やプログラミングシステムに関する情報が提供されています。ここにはユーザスペース側で永続型メモリを使用する際に便利な API を含む NVM ライブラリ (NVML) の説明もあります。

  • LIBNVDIMM: Non-Volatile Devices

    カーネル開発者向けの資料で、最新の Linux カーネルツリー内の Documentation ディレクトリ以下にある文書です。 NVDIMM の有効化に関わるカーネルモジュールに関する説明のほか、カーネル内の実装に関する技術詳細や ndctl ツールが使用する sysfs カーネルインターフェイスに関する情報などが提供されています。

  • GitHub: pmem/ndctl

    Linux カーネル内で libnvdimm サブシステムを管理するためのユーティリティライブラリです。ユーザスペース側のライブラリのほか、単体テストやドキュメンテーションなども提供されています。

このページを印刷