-
Notifications
You must be signed in to change notification settings - Fork 25
Home
PostgreSQLのshared_bufferの有無チェック -> BufTableLookup()で可能。BufferAlloc()を参照。共有ロック獲得用の関数もextensionから呼び出し可能。
Linuxのpage cacheの有無チェック -> find_get_page()で可能。do_generic_file_read()などが良いリファレンス。
NVMeドライバは /dev/nvme0n1p1 などのデバイスファイルを持ち、こいつに対して ioctl(2) を行う。 -> 対象のファイル自体ではない事に留意。
したがって、P2P DMAの対象ファイルとは別。 file descriptorをfget()関数に渡せばfile構造体をgetできる。最後にfputしてあげないとダメ。
対象ファイルから NVMe ドライバへのioctl()ハンドルを引く事はできる。 但し、実際には extra symbol を使って直接呼び出す。(余分なpage mappingを避けるため)
DMA_SSD2GPUの対象となるのは以下の3種類のソース
- ユーザ空間のバッファ ** shared_buffer上の領域(all_visible=1)のケース ** MVCCチェックで"不可視"判定のものを塗りつぶしたデータ(all_visible=0) ** このどちらも Lock 済みのページに配置されている事が前提
- Page Cache上のデータ(4KBアライン)
- SSD上のブロック(Block-Sizeアライン)
最初の二つはHost RAM->GPU RAMのDMAなので、async_memcpy()の仕組みを使えば 行けるハズ。 NVMe-SSDのDMA機構を使うのは最後の一個だけ。
VFSでI/Fが規定されているわけではない。 EXT4: ext4_get_block XFS: xfs_get_blocks のような関数コールが必要。これら関数はEXPORT_SYMBOL()されていないので、自前で関数ポインタをlookupしないとダメ。さらに、モジュールがunloadされたらシンボル:アドレスのペアをinvalidateする必要がある。 register_module_notifier()で登録可能。
DMなどが挟まっているケースでは、さらに物理ブロック位置を解決できるようにしないとダメ。 DBではRAIDほぼ必須なので、商用ライセンス版の独自機能にするか? RAIDの場合、同じファイルを複数のデバイスが構成する。->全てNVMeデバイスでないとダメというのは制約条件になるだろう。
TODO: ext4_get_block()で返されるblock_deviceは何を指すのか?たぶんDMデバイス。 物理的にNVMEなら何の問題もない。
いったんホストメモリにマップされた後という前提。 dmaengineを使うasync_memcpyという実装があるので、これを使えないかどうか確認。 DMA元がshared_bufferの場合、get_user_pagesしないとダメなはず。(コピーは不要?) page cacheならそのまま使えてほしい。
NVMe区画上に作ったファイルの filp->f_inode->i_sb を手繰ってみると、nvmeデバイス (major=254)ではなく、blkext(major=259)として見えている。 おそらく、こいつがNVMeデバイスをブロックデバイスに見せている。 block/genhd.c にて定義されている。BLOCK_EXT_MAJOR == 259 なのでチェックは容易。
i_sb->bd_disk を参照した結果 major = 259 first_minor = 0 minors = 0 disk_name = nvme0n1 fops = nvme_fops
=> これを使って NVME デバイスのioctl()をコールできるはず。
Ext4/XFSともに、非常に小さなファイルに対して"inline"化がされているケースがある。 通常、PostgreSQLデータファイルではあり得ないので、ioctl()が入った時に、サポート 外として弾いてよい。XFSのinlineチェックは? ext4_has_inline_data()
POSIX File Lockでwrite(2)へのプロテクトできるか?
-
nvme_fops 経由で ioctl を呼び出す。 -> コマンドの余計なコピーが入る。互換性は保てる。ライブラリとの協調作業になりそう…。
-
upstream kernelの場合、EXPORT_SYMBOL_GPU()がちょろちょろ。 -> これを見るのが先決か
-
RHEL7/CentOS7の場合 EXPORT_SYMBOL()が無いので、シンボルの自己解決が必要。
nvme_ioctl NVME_IOCTL_SUBMIT_IO -> nvme_submit_io
nvme_submit_io nvme_map_user_pagesとnvme_setup_prpを呼び、nvme_submit_io_cmd()をコール。 nvme_submit_io_cmd()への流れは NVME-Donard と同じ。
nvme_submit_io_cmd()は非staticなのでシンボル解決可能。 GPU Memoryをiodへマップしたりする辺りは、ほとんど同じ。
raid5.c の利用ケースでは、async_memcpy()をコール後、戻り値の tx を init_async_submit() にセット、async_trigger_callback() を呼び出していた。 両方とも汎用の関数でEXPORT_SYMBOL()されている。
NVMe-SSD側がSyncなので、先にメモリコピー発動、次にSSD->GPUが正しいか。
そもそもRAID1なら同じブロックに同じ内容を書き込むわけだから、DMデバイスの下さえNVMe-SSDと確認できればOK?