😕

brd: メモリ上に作成するブロックデバイス

2020/09/25に公開

はじめに

本記事はlinuxにおいてメモリ上に作成するブロックデバイスであるbrdというカーネルの機能について説明します。

用途

ブロックデバイスを直接しようする各種ファイルシステムやDB、partedなどのパーティショニングツールのテストが主な用途でしょう。とくに次のような場合には便利でしょう。

  • バックエンドがストレージデバイスであるときには時間がかかる加速試験の実行を高速化したい
  • 巨大なブロックデバイスが扱えるかを確認したい(後述するようにbrdにはブロックデバイスのサイズ制限が事実上無い)

使い方

機能が使えるかどうかの確認

まずはお使いのカーネルでbrdがサポートされているかを確認する必要があります。以下コマンドを実行した結果、"CONFIG_BLK_DEV_RAM=[ym]"という行が出てくれば使えます。そうでなければ当該機能が有効になっているカーネルを用意する必要があります(カーネルビルドについては本記事の対象外です)。

$ grep "^CONFIG_BLK_DEV_RAM=" /boot/config-$(uname -r)

例えばUbuntu 16.04のカーネルにおいてはモジュールとして提供されています(CONFIG_BLK_DEV_RAM=m)。

これ以降はbrdがモジュールとして提供されているとして話をします。

初期化方法

次のコマンド発行によってbrdを初期化します。

$ sudo modprobe brd

成功した場合は次のように/dev/ram*というブロックデバイスができます。

$ ls /dev/ram*
/dev/ram0  /dev/ram1  /dev/ram10  /dev/ram11  /dev/ram12  /dev/ram13  /dev/ram14  /dev/ram15  /dev/ram2  /dev/ram3  /dev/ram4  /dev/ram5  /dev/ram6  /dev/ram7  /dev/ram8  /dev/ram9

使用

/dev/ram*は全て通常のブロックデバイスと同様に使えます。たとえば以下は/dev/ram0上にBtrfsを作成する例です。

$ sudo mkfs.btrfs /dev/ram0
btrfs-progs v4.13.1
See http://btrfs.wiki.kernel.org for more information.

Performing full device TRIM /dev/ram0 (1.00GiB) ...
Label:              (null)
UUID:               638d68c2-ff24-44f2-9789-37309ba8cce7
Node size:          16384
Sector size:        4096
Filesystem size:    1.00GiB
Block group profiles:
  Data:             single            8.00MiB
  Metadata:         DUP              51.19MiB
  System:           DUP               8.00MiB
SSD detected:       no
Incompat features:  extref, skinny-metadata
Number of devices:  1
Devices:
   ID        SIZE  PATH
    1     1.00GiB  /dev/ram0

$ 

設定変更方法

brdが作成するデバイスの数、およびサイズはカーネルビルド時の設定によって異なります。たとえばUbuntu 16.04の場合はデバイスの数は16個、デバイスのサイズは64MBです。それぞれrd_nr, rd_rd_sizeというモジュールパラメタによって変更可能です。rd_sizeはKB単位ですデバイスの数を4個、デバイスのサイズを1GBにする例を示します。

$ sudo modprobe brd rd_nr=4 rd_size=$((1024*1024))
$ ls /dev/ram*
/dev/ram0  /dev/ram1  /dev/ram2  /dev/ram3       # デバイス数は4
$ LANG=C sudo parted /dev/ram0 p
Error: /dev/ram0: unrecognised disk label
Model: Unknown (unknown)
Disk /dev/ram0: 1074MB                           # サイズは1GB
Sector size (logical/physical): 512B/4096B
Partition Table: unknown
Disk Flags:

rd_sizeはシステムに搭載したものよりも大きいものを設定できます。brdは初期化時にデバイスに必要なメモリをすべて確保するのではなく、オンデマンドにメモリを獲得します。具体的には、内部的にはデバイスの領域をページ(x86_64の場合は4KB)単位に区切って管理しており、各ページに対して最初にアクセスしたときにページごとにメモリを獲得します。

終了方法

brdが作ったデバイスが不要になったら次のコマンドによってモジュールを削除します。このときbrdが使用していたメモリを解放します。

$ sudo modprobe -r brd

他の類似機能との違い

tmpfsとの違い

brdとtmpfsはメモリベースであることは同じなのですが、tmpfsはユーザにファイルシステムを提供するのに対してbrdはブロックデバイスを提供するというところが違います。つまりレイヤが異なります。

ファイルのループバックマウントとの違い

何らかのファイルシステム上に作成したファイル上にファイルシステムを作成してループバックマウントすることによって、ファイルシステムのテストはできます。sparseファイルを作れば大容量ファイルシステムも作成できます。しかしループバックマウントにおいてはファイルシステムにアクセスするごとにストレージの容量を消費してしまうという点が異なります。

おわりに

開発状況については、brdはかなり枯れた機能であり、2,3か月に一度のlinuxのバージョンアップごとに数個パッチが入る程度です。

機能がシンプルなせいもあり、brdのソース(drivers/block/brd.c)はたったの600程度なので、ブロックデバイス層の最も単純な実装を理解したいというかたは見てみると面白いでしょう。

Discussion