37
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

FUJITSUAdvent Calendar 2022

Day 25

2022年の不揮発メモリとLinux対応動向について

Last updated at Posted at 2022-12-25

この記事は、Fujitsu Advent Calendar 2022の25日目の記事です。

「え、まだこのネタで書くの?」と思う方もいらっしゃるかもしれませんが、ええ、今年もこのネタで書きます。

1. NVDIMMの終焉とCXLの台頭

1.1 Intel Optane Persistent Memory

これを読む皆さんはおそらくご承知のことでしょう。NVDIMMの最有力製品であったIntel Optane Persisntent Memoryのビジネスは、残念ながら終焉に向かうことが以下のように発表されました。

In Q2 2022, we initiated the winding down of our Intel Optane memory business.

実は発表と同時にすぐに製品出荷を終了してしまったわけではありません。以下の記事から少し引用します。

既存のOptane永続化メモリやOptane SSD製品群については、Optaneのユーザーを耐用年数の終了までサポートすることが約束されました。Intel製品の保証条件に変更はなく、通常の5年保証によって、この保証期間中はテクニカルサポートを受けられます。

また、第4世代インテル®Xeonスケーラブルプロセッサー(コードネーム「Sapphire Rapids」)搭載のインテル®Optaneパーシステントメモリ(PMem)300シリーズ(コードネーム「Crow Pass」)についても開発を継続するとのことです。

Sapphire Rapidsの出荷は2023年が予定されていますから、それに合わせて製品としてはもう少しサポートが続くといってよいでしょう。

とはいえ、IntelがOptane Persistent memoryをギブアップするのは早すぎたし、3DXpointもこのまま消えていくのは正直勿体ないと感じています。性能測定もしてみましたが、3D Xpointの性能自体は確かに他の不揮発デバイスよりも優秀でした。NVDIMMとしてはダメだったかもしれませんが、3D XpointがCXLの不揮発メモリデバイスとして復活を遂げてくれると個人的には嬉しいのですが、ちょっと厳しいだろうなぁ…。

それに、新たな技術が出たとしても、それに対するよいユースケースが見つかったり、使いこなされて普及されるようになるまでには非常に時間がかかるものです。Dockerが流行る前にもコンテナー技術はSolarisコンテナーなどずいぶん前から存在していたわけで、最も良いユースケースが見つかるまでは何年もかかっているはずです。

せめて、IntelはCXLベースの不揮発メモリの製品がリリースされた後に撤退の発表をしてくれたら、今少し悪い印象を防げたのではないかと思うのですが…。世の中、中々難しいものです。

1.2 進捗が進んできたCXL

さて一方で、今年はCompute Express Link(CXL)は元気いっぱいでした。昨年の記事ではCXLにも不揮発メモリが搭載されることについて言及していましたが、そのCXLは2022/8/1には最新仕様として3.0が公開されたうえ、同日にライバル仕様であったOpen CAPIを吸収したことも発表されました。

そうすると残りのライバルはCCIXなのですが、CCIXのプレスリリースは2021年9月を最後に更新されていません。また、CCIXの主要メンバー企業はCXLにも二股をかけている状態なので、どっちが勝っても問題ない形になっています。こうなると、事実上CXLが勝ち残った1と考えても良いでしょう。

昨年から今年にかけて、CXLの仕様について私も本格的に勉強を始めたのですが、その結果CXLについていくつか講演依頼をいただいたり、海外出張してCXL仕様について議論する機会を得たりもしました。そういう意味では私にとって2022年は充実した一年ともなりました。

CXLについて私が講演した資料は以下の通り公開していますので、詳しい説明はそちらに譲ります。ご覧になっていただけると幸いです。

上記の資料のとおり、CXL3.0において共有メモリやFabricの定義が入ったことは個人的に意義が大きいと考えています。今後の分散システムの鍵を握るインフラとなることは間違いないでしょう。

また、調査した今年8月の時点ではまだコミュニティで実装中であったため、上記の資料ではシステム起動時のドライバが必要としていましたが、最新のCXL開発サブツリーを参照すると、以下のようにACPIテーブル(ここではCFMWS)の読み取り(parse)の実装など、システム起動時に必要な処理がマージされてきていました。昨年よりも着実に開発が進捗していることがうかがえます。コードの解説はここではしませんが、興味がある人は調べてみると面白いかもしれません。

drivers/cxl/acpi.cより抜粋
  :
  :
static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
                           const unsigned long end)
{
        int target_map[CXL_DECODER_MAX_INTERLEAVE];
        struct cxl_cfmws_context *ctx = arg;
        struct cxl_port *root_port = ctx->root_port;
        struct resource *cxl_res = ctx->cxl_res;
        struct cxl_cxims_context cxims_ctx;
        struct cxl_root_decoder *cxlrd;
        struct device *dev = ctx->dev;
        struct acpi_cedt_cfmws *cfmws;
        cxl_calc_hb_fn cxl_calc_hb;
        struct cxl_decoder *cxld;
        unsigned int ways, i, ig;
        struct resource *res;
        int rc;

        cfmws = (struct acpi_cedt_cfmws *) header;

        rc = cxl_acpi_cfmws_verify(dev, cfmws);
        if (rc) {
                dev_err(dev, "CFMWS range %#llx-%#llx not registered\n",
                        cfmws->base_hpa,
                        cfmws->base_hpa + cfmws->window_size - 1);
                return 0;
        }

        rc = eiw_to_ways(cfmws->interleave_ways, &ways);
        if (rc)
                return rc;
        rc = eig_to_granularity(cfmws->granularity, &ig);
        if (rc)
                return rc;
        for (i = 0; i < ways; i++)
                target_map[i] = cfmws->interleave_targets[i];

        res = kzalloc(sizeof(*res), GFP_KERNEL);
        if (!res)
                return -ENOMEM;

        res->name = kasprintf(GFP_KERNEL, "CXL Window %d", ctx->id++);
        if (!res->name)
                goto err_name;

        res->start = cfmws->base_hpa;
        res->end = cfmws->base_hpa + cfmws->window_size - 1;
        res->flags = IORESOURCE_MEM;
  :
  :

2. 従来から取り組んできた開発の進捗状況

さて、ハードや仕様の話はこれくらいにして、私のチームでずっと続けてきたLinuxの不揮発メモリ対応の話をしましょう。なお、これらの機能はNVDIMMだけでなく、今後出てくると思われるCXLの不揮発メモリでも有効です。

2.1 Filesystem DAXの状況

まずはFilesystem DAXの状況について述べないといけません。

2021年のLinux Plumbers Conferenceにおいて、私やチームメンバーのRuanさんが報告した内容、特にXFSのreflink機能とFilesystem-DAXの間の問題点を解決するための必要なパッチが おおむねkernel6.1に取り込まれました。 このため、「これでようやくExperimentalとされていた状態も解除される」とを期待していたのですが、残念ながら開発コミュニティから新たに「warningメッセージが表示される」などのトラブルが報告されてしまいました。このため、 もう少し障害修正に取り組まないといけなくなっている状態です。

この中でも、コミュニティで一番問題視されている障害について一言でまとめると、
Filesystem側のブロックの利用状況の状態変化メモリ管理機構が追い切れていない
という問題だと言えます。

Filesystem DAXは「ストレージであると共にメモリでもある」ので、両方の間をうまく取り持つ必要があるのですが、ソフト側のFilesystem DAXへのアクセスパターンによっては、そのファイルシステム側の変化に対してメモリ側がついていけないパターンがあったということです。つまり考慮漏れですね2

これらの問題については以下のパッチをはじめ、現在私のチームで修正に取り組んでいます。いくつかはメインラインにマージされてきていますが、まだ完全に問題が解決したわけではないので、今少し時間が必要な状態です。
https://lore.kernel.org/lkml/1669908538-55-1-git-send-email-ruansy.fnst@fujitsu.com/

プロプラエタリな製品であれ、OSSであれ、システムを最後まで完成させるまでには 生みの苦しみ みたいなものがありますが、どうやらFilesystem DAXの開発も最終局面においてそのような状態になってきているようです。

2.2 不揮発メモリ向けRDMAの新仕様の状況

昨年の記事では、InfinibandのRDMAに不揮発メモリ向けの新仕様、flushとatomic writeについて解説しましたが、皆さん覚えていらっしゃいますでしょうか?

それらの仕様は基本的にinfinibandのハードベンダーが対応するべき仕様であるため、、対応した製品およびそのドライバが提供されるまでは、我々は使うことができません。また、そのようハードを購入するというのは稟議など社内手続きを踏まえて買わないといけないとなると、利用するまでのハードルは高いと言えるでしょう。

そこで、SoftRoCEにこれらの新仕様をエミュレーションするということを私は昨年の段階で考えていて、今年はその機能の実装に取り組んでいました。これついては、以下のようにメインラインにドライバがマージされてきていて、時期的におそらく6.2-rc1には入りそうな感触です。

commit 124011e6e933bead5852c3f69b32dec43919fe1a
Author: Li Zhijian <lizhijian@fujitsu.com>
Date:   Tue Dec 6 21:02:01 2022 +0800

    RDMA/rxe: Enable RDMA FLUSH capability for rxe device

    Now we are ready to enable RDMA FLUSH capability for RXE.
    It can support Global Visibility and Persistence placement types.

    Link: https://lore.kernel.org/r/20221206130201.30986-11-lizhijian@fujitsu.com
    Reviewed-by: Zhu Yanjun <zyjzyj2000@gmail.com>
    Signed-off-by: Li Zhijian <lizhijian@fujitsu.com>
    Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
:
:
commit 4cd9f1d320f905e7bc60f030566d15003745ba91
Author: Xiao Yang <yangx.jy@fujitsu.com>
Date:   Thu Dec 1 14:39:28 2022 +0000

    RDMA/rxe: Enable atomic write capability for rxe device

    The capability shows that rxe device supports atomic write operation.

    Link: https://lore.kernel.org/r/1669905568-62-4-git-send-email-yangx.jy@fujitsu.com
    Signed-off-by: Xiao Yang <yangx.jy@fujitsu.com>
    Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>

さらに、infinbandのインタフェースでSoftRoCEのこれらの新仕様対応の機能を利用するためには、この上位のライブラリlibibverbs(rdma-core)パッケージの中の一つ)も修正する必要がありますが、そちらの方も現在対応が進んでいます。atomic writeについてはもうすでにpull requestがマージされており、flushについてもあともう少しといった状況です。

さらに不揮発メモリ向けのRDMAライブラリであるlibrpmaについても新仕様対応を始めています

これらについては、今年は大きく前進したと言えるでしょう。

3. RDMAのOn Demand Paging機能

3.1 RDMAを使った時の課題

昨年のAdvent Calendarの記事では不揮発メモリに対するRDMAの重要性や、不揮発メモリ向けの新仕様について解説しました。しかし、上記のLinux Plumbers Confrenceの発表の16pageにおいて、以下のように記載していたことに気が付いていた人はどれくらいいるでしょうか? "On Demand Paging"がworkaroundになっているとしています。また、これについては2020年のAdvent Calendarの記事でも取り上げていました。

ODP_IS_needed.png

今回は、このOn Demand Pagingについてもう少し詳しく取り上げたいと思います。このため、まずはこのworkaroundが出るまでの背景についておさらいしましょう。

そもそも、これまで述べてきたように、Filesystem-DAXは不揮発メモリ上にファイルシステムを構築して、あるユーザプロセスがそのファイルをmmap()すると、そのファイルのブロックはそのユーザプロセスのメモリ領域として直接割り当てられ、その後はユーザプロセスがはカーネルやドライバを介さず直接不揮発メモリにread/writeする機能です。

さてここで「もしものケース」を考えてみましょう。

  • あるプロセスが利用中のファイルに対して、
  • 同時に隣でtruncate()やpunch holeなどの操作をユーザが行うことで、「そのブロックを使わない」という処理

が行われたらどうなるでしょうか? 本当はまだデータ転送中のブロックがファイルシステムからは未使用扱いにされてしまいます。その結果、そのブロックに転送したはずのデータが無くなってしまったり、ファイルシステムがそのブロックを再利用することで、ユーザのデータ破壊や最悪ファイルシステムの破壊なども起こりえる...というわけです。

RDMA_vs_truncate.png

もちろん普通はそんなことができないように、デバイスドライバが対象のブロックを固定して回避するようにしますが、それはそれで今度はファイルシステムとしてはいつまでもtruncate()やpunch holeといった操作ができないわけですから困ってしまいます。

特に、これまでInfinibandやVideo for linux(V4L2)のようにkernel/driverレイヤのバッファを経由するのではなく、ユーザーのプロセス領域に直接DMA/RDMAで書き込みを行うデバイスでは、そのような領域にいつまでもデータ転送が実行され続け、ユーザが良しというまで終わらないという問題があります。これを待つというのは非常に困難です3

ではどうすればよいのか?というところで、事実上最後の手段として挙げられているのがOn Demand pagingという機能というわけです。

3.2 On Demand Pagingとは何か

On Demand Pagingとは何かというと、もともとは「DMA/RDMAでデータ転送する領域に対して、kernelによってページ回収されることをデバイスが許す機能」といえるでしょう。
通常のハードウェアはDMAやRDMAでハードからメモリにデータ転送中の間に、その対象となっているメモリがLinuxのメモリ回収処理などによってSwap outされたりしないように、pageをpin downすなわちページ固定します。もしデータ転送中にkernelがそれを知らずにswap outしてしまわないようにする必要があるのです。
しかし、そういう領域があまりに大きいサイズだと、Linux Kernelから見ると「ページ回収ができない領域が無視できないぐらい大量に存在する」状態になります。これはシステム全体から見ると健全な状態とは言えません。このため、kernelがページ回収したらそのことをデバイス側で検知し、デバイスがもう一度その領域にデータ転送したい場合はデバイス側が起点となってpage faultの処理を起こすことができれば良い…という発想が出てきます。これがOn Demand pagingです。

On Demand Pagingの動作については以下の資料が分かりやすいので、この図を使って説明しましょう。
On Demand Paging for User-level Networking

kernelのメモリ回収処理が動作したときのために、デバイスドライバーはmmu_notifierという機能のハンドラーをあらかじめ登録しておくことができます。実際に回収処理が走った(invalidation)時にこのハンドラーが呼ばれますが、ドライバ内部のメモリ領域の管理を更新するほか、デバイス側にも対象のページがpage回収処理によってメモリ上からなくなることを伝達します。

ODP_Invalidation.png

逆に今度はデバイス側から、回収されたページのデータにもう一度DMA/RDMAなどで転送したい場合は、デバイス側が起点となってpage faultの処理をキックすることができます。

ODP_Page_in.png

Infinibandといえば、現在はNVIDIAに買収されたMellanoxの製品が有名ですが、現在On Demand PagingをサポートしているハードウェアはこのNVIDIAの比較的新しめの製品だけです。

3.3 Filesystem DAXとOn Demand Paging

さて、このOn Demand Paging,ここまで読んで疑問に思った方もいるかもしれません。swap outするのはmalloc()で確保したメモリなど、ファイルに結び付けられていない所謂 匿名ページ のはずで、Filesystem DAXは関係ないのでは?と考えるのは自然なことです。

実は、このpageを無効化するinvalidateのハンドラーはFilesystem DAXの場合でも有効で、前述のtruncate()やpunch holeなどの操作をユーザーが行った時に、これが呼び出されるようになっています。

このため、もしtruncate()やpunch holeなどで転送中のページが無くなる場合でも、このハンドラー経由でデバイス側が転送先が無くなったことを検知できます。逆に転送先にデバイスが新たにアクセスしたくなった場合には、デバイス手動でpage faultを起こして領域を再確保できるというわけです。

3.4 SoftRoCEでOn Demand Paging

さて、Mellanox(現NVIDIA)の機能はプロプラエタリドライバのほか、OSSとしてlinux kernelに付随したドライバもあるのですが、このドライバの素晴らしい所は、このOn Demand Pagingの機能を有しているのはMallanoxだけだったにもかかわらず、他のハードウェアでもOn Demand Pagingを搭載した場合にも対応できるように、ソースコード上共通化できる個所をきちんと切り分けていていることです。
Infinibandのドライバは以下のような構成になっていますが、このうち、core/umem_odp.cのところに、共通で使えるOn Demand Pagingのソースコードが分離されています。

drivers/inifinband/core -----------------> infinband 共通層のソースが入るディレクトリ
                  /core/umem_odp.c ------> 共通層のOn Demand Pagingのソースコード
                  /hw   -----------------> 各デバイスベンダー固有のドライバのディレクトリ
                  /hw/mlx5 --------------> Mellanoxの比較的新しいカードのドライバのディレクトリ
                  /hw/mlx5/odp.c --------> Mellanox固有のドライバのOn Demand Pagingのソースコード
                  /sw      --------------> SoftRoCEのように他の機能とソフト的に連携して機能を実現するためのディレクトリ
                  /sw/rxe  --------------> SoftRoCEのドライバのディレクトリ

この実装に気が付いた筆者は、 「これ、共通化部分をうまく使えばSoftRoCEのドライバでもOn Demand Pagingの機能を実現できるんじゃね?」 と思い立ちました。前述したように、SoftRoCEなら新しいハードウェアを購入するといった手間が無くても気軽に試せるからです。そこで大まかな設計方針を筆者の方で決めて、そのあとの具体的な論理設計からは筆者のチームのホープであるMatsudaさんに任せ、パッチをコミュニティに投稿してもらっています。

もっとも、現在の段階ではまだ機能的に不足しているところがあります。

  • 前述の不揮発メモリ向け新仕様(flush, atomic write)に未対応
  • page faultする分、性能的には遅くなることが考えられるので、それを緩和するためのprefecth機能の実装が必要となるが、今の段階では未実装
  • etc.

可能であれば、上記についても今後対応していきたいと考えています。

なお、このパッチについて、RDMA全体を統括するメンテナーの一人からは、「こんなクールな機能なのに(レビューがあまりされていなくて)進捗していなくて残念だ。誰かレビューしてくれないか?」といったコメントが出ています。実はSoftRoCEはレビューワーが慢性的に不足気味で、筆者も困っているところです。
丁度つい先日v3版を投稿したところでもあるので、もしよろしければSoftRoCEやこのパッチのレビューに参加していただける方がいらっしゃると、大変ありがたく思います。

4.まとめ

今年の状況をまとめた…というよりは筆者の周辺の状況をまとめた形になっていますが、いかがだったでしょうか?来年は本格的にCXL周りの開発をしたいと考えていますが、まだまだ検討中の段階です。引き続きLinux Kernelに貢献していきたいと思うのでよろしくお願いします。

それではよいお年を!

  1. CPU以外のデバイスの販売に関してIntelはどうもイマイチぱっとしませんが、この手の仕様の標準化に関しては手堅いなと思うことがあります。 これまでPCIやPCI expressなどの仕様もIntelの影響が大きいものでした。また、何よりも優秀なLinux Kernelエンジニアを抱えていて、Linuxに取り込まれている数も相当なものがあります。この多数の優秀なエンジニアによって、Linuxにおいてデファクトスタンダードを作り上げてしまう力が、私は見逃してはならないIntelの強みだと考えています。

  2. 正直これは私にも責任があると思っていて、網羅性確認とかのチェックとか、再発防止の施策をしていかないといけないと思っています。ツライ…。

  3. 実はIntelはRDMA対象となっている場合、truncate()やpunch holeのようなファイルのブロックを変更するような操作をリジェクトするというlayout leaseというインタフェースを提案していました。しかし、コミュニティでは事実上提案がrejectされた状態になっています。使い方が難しいというのが主な理由ですが、より詳しくはDave Chinnerのこのあたりの意見を参照すると良いかもしれません

37
27
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?