Skip to content

Instantly share code, notes, and snippets.

@4ge32
Last active February 20, 2019 08:56
Show Gist options
  • Save 4ge32/41229cae3f63bbd1e3f2d6350ae98ec6 to your computer and use it in GitHub Desktop.
Save 4ge32/41229cae3f63bbd1e3f2d6350ae98ec6 to your computer and use it in GitHub Desktop.
環境の作り方とAEONの試し方

前提条件

基本的にはFedora28以上を入れておくのが一番簡単かと思います. Linuxカーネルはバージョンが4.17.19以上である必要があります. Linuxカーネルは以下のコンフィグが有効になっている必要があります. 最近の一般的なディストリビューションだと有効になっていることが多いとは思いますが, 自前でカーネルをビルドする場合や機能が有効にならない場合は有効化・確認をする必要があります.

CONFIG_BLK_DEV_RAM_DAX=y
CONFIG_FS_DAX=y
CONFIG_X86_PMEM_LEGACY=y
CONFIG_LIBNVDIMM=y
CONFIG_BLK_DEV_PMEM=m
CONFIG_ARCH_HAS_PMEM_API=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_MEMORY_HOTPLUG=y
CONFIG_MEMORY_HOTREMOVE=y
CONFIG_ZONE_DEVICE=y
CONFIG_FS_DAX_PMD=y

NVDIMMのエミュレート方法

NVDIMMをエミュレートする方法は2つあります.一つは完全に仮想環境上で,一つは実機上でできます. とりあえずQEMUを使用しておくのが簡単だと思います.

QEMUを使う

QEMUがファイルをバックエンドにNVDIMMをエミュレートしてくれます. 僕は以下のシェルスクリプトで仮想環境を立ち上げています.

#/bin/sh

RAM_SIZE=16G
NVDIMM_SIZE=64G
ePATH=.
DISTRO=fedora.qcow2
GRAPHIC=-nographic
MAX_SIZE=300G
CPU=host
CORE=16


run() {
  qemu-system-x86_64 -enable-kvm $GRAPHIC -s \
                     -drive file=$DISTRO,index=0,media=disk,cache=none \
                     -machine pc,nvdimm                \
                     -m $RAM_SIZE,slots=4,maxmem=$MAX_SIZE \
                     -smp $CORE -cpu $CPU              \
                     -net nic,model=virtio             \
                     -net user,hostfwd=tcp::2222-:22   \
                     -object memory-backend-file,share,id=mem1,share=on,mem-path=$ePATH,size=$NVDIMM_SIZE \
                     -device nvdimm,id=nvdimm1,memdev=mem1 &
}

connect() {
  ssh -p 2222 -i ~/.ssh/nvm_rsa pmem@localhost
}

case "$1" in
  run)
    run 
    ;;  
  r)  
    run 
    ;;  
  connect)
    connect
    ;;  
  c)  
    connect
    ;;  
  *)  
    ;;  
esac
exit 0

これをそのまま真似るだけでも64GBの/dev/pmem0が認識された仮想環境が立ち上がるはずです. 普段は適宜引数を変えることで仮想環境上のNVDIMMやDRAMのサイズを調節しています. 参考サイトはこちらになります. 日本語ソースだと自作OSでできる!NVDIMMのつかいかたを読むのが分かりやすくて良いかと思います.

システムのDRAMの一部を使う

DRAMの一部を使用してNVDIMMをエミュレートすることも可能です.これはカーネルパラメータを追加してやることで可能になります. 仮想環境の必要なしに行うことができますが,仮想環境上でやることをおすすめします. Fedora(Ubuntuも同様であると確認済み)だと/etc/default/以下にgrubというファイルがあります.

GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=0
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="resume=/dev/mapper/fedora_localhost--live-swap rd.lvm.lv=fedora_localhost-live/root rd.lvm.lv=fedora_localhost-live/swap rhgb quiet crashkernel=128M memmap=8G!8G"
GRUB_DISABLE_RECOVERY="true"

僕のFedora28環境だと上のようになっています.このうちmemmap=8G!8G!というのがNVDIMMエミュレートするためのカーネルパラメータです. **注意事項として,これはメモリが16GBだった時の環境上でのみ通用するパラメータです.**パラメータの設定方法は後述します. パラメータを追加し,grub2-mkconfig -o /boot/grub2/grub.cfgと叩いてgrubを更新してシステムを再起動すると8G/dev/pmem0をシステムが 認識します.

パラメータの意味やこぼれ話

簡単に言ってしまうとメモリ8Gから先の8GをNVDIMMとしてエミュレートするというパラメータになります.最初の8Gがどのくらいのサイズの NVDIMMをエミュレートするか,次の8Gがメモリのどこからエミュレートするかということを表します. このエミュレーション方法はいくつか制約があります.一つはシステムに与えられたメモリを超えた指定を行えないことです.また,システムが 予約しているメモリ領域をNVDIMMとして使う指定をすることはできません. 詳細はPersistent Memory WikiのQuick Setup Guidにあります.このエミュレーション方法を利用したい場合は読むことをおすすめします. この方法は設定が少々わかりにくいですが一つ利点があります.それはDRAMを利用したエミュレーションであるため,NVDIMM-Nをディスクとして使用する際の ベンチマークをある程度正確に採ることが出来ます.これは個人的に非常に興味深かった点ですがQEMUを用いたエミュレーションによって ベンチマークを採るとNOVAとAEONは全く性能が出ません.一方,DRAMを用いたエミュレーションでは先行論文から得られる結果を含めた期待通りの スコアを概ね得ることができます.これは個人的に割と面白い知見でした.

両方使う

両方同時に使うこともできます.僕は普段はDRAMを用いたエミュレーションで開発しており,テスト時に複数のデバイスが必要になる場合にQEMUのオプションを 追加して(厳密に言うとコメントアウトを外している)複数を扱っています.もっともQEMUだけで複数のデバイスをエミュレーションすることも可能です.

マウント方法

NVDIMMが無事エミュレートできたらマウントしてAEONを試すことができます. AEONを手元に持ってきてmakeでビルドしてください.もしビルドできなかったらissue立ててください... aeon.koというバイナリができます.以下のコマンドでカーネルに組み込んでください.

# insmod aeon.ko

次に,NVDIMMをFSDAXモードに変更します./dev/pmem0に対するコマンドは以下になります.

# ndctl create-namespace -e "namespace0.0" -m memory -f

これで,マウントに移ることができます.

# mount -t aeon -o init,dax /dev/pmem0 /mnt

マウント先は任意です.最初のマウントはinitをつける必要があります.またdax常に必ずつけてください. ファイルとか色々作った後にファイルシステムをアンマウントする時は, 次のコマンドで行います.

# umount /mnt

以降,initなしにマウントできます.作ったファイルも認識されるはずです.(ちなみにデモのmkfs.aeonは単に このコマンド群を組み合わせたシェルスクリプトです.近いうちにC/C++でmkfsコマンドを作ろうと考えています.) ただし,実機がない場合は,システムを落としたらinitからやり直してください.作ったファイルはなくなります. これら一連の流れは同梱のrun.shを使用して

$ make -j
$ ./run.sh  set
$ ./run.sh 

とやるのが簡単です.(普段はこれで開発をしています.)

透過圧縮を使う

Fedora28だと通常zsdモジュールがインストールされていないので透過圧縮モードでAEONをマウントすることはできません.

# modprobe zstd_compress
# modprobe zstd_decompress

これで,使えるはずです.ただし僕はカーネル自前ビルドしてzstd使っているのでもしかしたらできないかも... また確認します. また,AEONを透過圧縮のコンフィグをオンにした状態でビルドしたものを使う必要があります. Makefile中の CONFIG_AEON_FS_COMPRESSIONCONFIG_AEON_FS_AEON_RWをコメントアウトしてビルドしてください. (いまのところ透過圧縮はまだ解決すべき課題がいくつかあるのですぐバグります.ある程度まともに動くようになるまで少し時間がかかると思います) マウント時にマウントオプションにdata=compressedを追加してください.run.shを用いて

$ ./run.sh compression

でも良いです.

Makefile中のCONFIGの意味

CONFIG_AEON_FS_XATTRCONFIG_AEON_FS_SECURITYsetfattrコマンドやgetfattrコマンドを使用する際に必要になります. CONFIG_AEON_FS_COMPRESSIONCONFIG_AEON_FS_AEON_RWと一緒に有効化する必要があります. CONFIG_AEON_FS_AEON_RWは自前の読み書きメソッド実装モードになります.これ単体でビルドした場合はLinuxカーネルの共通関数を用いた読み書きではなく全て自前実装の読み書きメソッドが使われます. CONFIG_AEON_FS_DEBUG_MODEは デバッグ用にログをたくさん吐くようになります.残り3つのオプションは内部の管理方法が変わりますが,CONFIG_AEON_FS_NUMAに関しては masterブランチのものでは実際にはNUMAのためのモードになりません.もっともNUMA構成のNVDIMMをエミュレートする手段がない(はず)のですが...

バグ報告

いくつかバグを確認していますが,確認できていないバグがある可能性は十分にあると思いますので,issueにバグレポートのテンプレ用意しておきましたので, もし見つけたら立てていただければ嬉しいです.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment