dmraidの仕様

5月23日に、dmraid-1.0.0.rc8のアナウンスが行われた。1.0.0-rc1が出たのが去年の7月だから、rc(release candidate)が出てから、約1年近く経っても正式リリースがされないことになる。

LKML等でのdmraid-1.0.0.rc8のリリースメールには、以下のようにある。

このリリースでは、NVidiaでのストライプサイズのバグを直し、Silicon Imageの実現番号(incarnation number)を、適切にグループ化できないセットは無視して、RAID名生成に使用しないようにした。
次ののATARAIDタイプがサポートされている。
  • Highpoint HPT37X
  • Highpoint HPT45X
  • Intel Software RAID
  • LSI Logic MegaRAID
  • NVidia NForce
  • Promise FastTrack
  • Silicon Image Medley
  • VIA Software RAID

dmraidの現状については、「dmraidの苦悩(その1)」「dmraidの苦悩(その2)」の過去2回の記事に記述した。今回はdmraidの機能と仕様について紹介する。

dmraidの品質はこれまで紹介してきた通り、決して良好とは評価できるものではなかった。しかしtarballのdoc/dmraid_design.txtには、的を得た「あるべき姿」を記述している技術仕様がある。このdmraidは、主にWindows向けとなっているベンダ個別のRAIDコントローラをオープンソースの環境で利用するためには、今後不可欠な技術でもある。カーネル2.6で実装されたdm(Device mapper)の応用事例として、その内部構造を紹介するのに適しているので、その内容を紹介する。

はじめに

dmraid(ツール)は、Device-mapper(dm)を備えたLinuxカーネル2.6において、ベンダ固有の(バイナリ)ドライバをインストールせずに、(カーネル2.4の)ATARAIDのようなRAIDデバイス(RD)をサポートするものである。これは複数のオンディスクRAIDメタデータ・フォーマットをサポートし、新しい拡張にも対応可能なものである。

まずdmraidは、RAIDデバイスの開始をサポートすることを目標としていて、ディスク故障時等でのオンディスクRAIDメタデータの*更新*はサポートしない。またディスク・メタデータ上に、複数のデバイスのフォーマット・シグネチャがある場合には、消すことができる。

将来の機能拡張については、最後に記述する。

要求機能

  1. dmraidは以下の複数ベンダのオンディスクRAIDメタデータ・フォーマットを読み取る必要がある。(訳注:開発当初の目標だと思われる)
    • ATARAID
      • Highpoint 37x/45x
      • Intel Software RAID
      • LSI Logic MegaRaid
      • Promise FastTrak
      • Silicon Image Medley
  2. dmraidはSNIA DDFのような、他のオンディスクRAIDフォーマットによる、将来の拡張に対応する。
  3. dmraidは、RAIDデータをアドレスするために必要とされるマッピングを定義するために必要な、dmテーブルを生成するものとする。
  4. デバイスの検出、開始(activation)、停止(deactivation)、およびプロパティの表示機能をサポートする。
  5. スパンニング・ディスク、RAID0、RAID1とRAID10をサポートし、さらにSNIA DDFをサポートを可能にするために、RAID5のような、より高いRAIDレベルをdmターゲットの形式で実装することが必要である。(訳注:現在のカーネルでは、SPAN / RAID0 / RAID1だけが、dmによってサポートされている)
  6. RAIDセット中のMSDOSパーティションの開始をサポートする。

機能セットの定義

デバイスの検出、開始、停止、プロパティの表示の各機能について、以下に概要を示す。

  • 検出 (1からn個までのRAIDデバイス)
    1. RAIDデバイスを識別するために、 アクティブなディスクをスキャンする。
    2. RAIDデバイス・シグネチャを探して、それが認識できればデバイスを検出済みRAIDデバイスのリストに追加する。
    3. RAIDデバイスのレイアウトを記述してあるメタ・データを抽象化して、その中にベンダ固有のフォーマットを変換する。
  • 開始 (1からn個までのRAIDデバイス)
    1. 各レイアウト(SPAN, RAID0, RAID1, RAID10)に合わせて抽象化したRAIDセットへ、デバイスをグループ化する。
    2. RAIDセットとRAIDデバイスに関して抽象化した情報に基づき、RAIDセットのためのdm mapping tablesを生成する。
  • 停止
    1. RAIDセットを構築するdmデバイスを削除する。それは、RAID0デバイス上にRAID1が構築してあるというように、デバイスが階層化されている場合がある。
  • 表示
    1. RAIDセットとRAIDデバイスのプロパティを表示する。

技術的な仕様

intまたはポインタを返すファンクションはすべて、失敗した場合に0またはNULLを返す。

  • RAIDメタデータ・フォーマット・ハンドラ

    ツールはベンダ固有のフォーマット・ハンドラを登録するために次の関数を呼ぶ。成功した場合は、メソッドを備えた新しいインスタンスが、上位レベルのメタデータを扱うファンクションにアクセス可能になる。

    • int register_format_handler(struct lib_context *lc, struct dmraid_format *fmt)

      フォーマット・ハンドラの登録に成功した場合は、0以外を返す。

    フォーマット・ハンドラ・メソッド

    • struct raid_dev *(read)(struct lib_context *lc, struct dev_info* di)

      オフセットや領域サイズといった、RAIDデバイスの構造を記述する’struct raid_dev *’を返す。

    • int (*write)(struct lib_context *lc, struct raid_dev* rd, int erase)

      各RAIDデバイス’rd’に対して、ベンダ固有のメタデータの書き出しに成功した場合は0以外を返す。オプションとして、eraseが0以外の場合はメタデータ領域を削除する。

    • struct raid_set (*group)(struct lib_context *lc, struct raid_dev *raid_dev)

      成功した場合は、RAIDセット構造体へのポインタを返す。

    • int (*check)(struct lib_context *lc, struct raid_set *raid_set)

      RAIDセットの整合性を確認した場合は、0以外を返す。

    • void (*log)(struct lib_context *lc, struct raid_dev *rd)

      RAIDデバイス’rd’の、本来のフォーマット(各ベンダ固有のフォーマット)でメタデータを表示する。

  • 検出
    1. /SYSFS_MOUNTPOINT/block/[sh]d*をスキャンすることにより、全てのディスクデバイス用のsysfsからブロックデバイス情報を検索する。デバイス上で ‘struct dev_info *’型のリンクリストにおいて、RAIDシグネチャを検出すためのデバイス・パスとサイズに関する情報を維持する。
    2. リストをたどって、デバイスからRAIDデバイス・メタデータ・シグネチャを読むために、(Highpoint等に見られる…)ベンダ固有のREADメソッドを順番に試す。ライブラリでは将来の拡張で公開させるために、ベンダ固有のRAIDフォーマット用のフォーマット・ハンドラを登録するインタフェースを開示している(上記register_format_handler()を参照)。

      ツールは、すべての登録されたフォーマット・ハンドラ・メソッドの繰り返し操作を隠す、次の上位レベルの関数を呼ぶ。

    • void discover_devices(struct lib_context *lc)

      全てのサポートしているディスク(IDE, SCSI)を検出した場合には、0以外を返し、リストに登録する。

    • void discover_raid_devices(struct lib_context *lc, char **fmt_names, char **devices)

      discover_devices()で追加されたリストを使用して、全てのサポートしているRAIDデバイスを検出する。

    • void discover_partitions(struct lib_context *lc)

      有効なRAIDセット中の全てのMSDOSパーティションを検出し、各パーティションで開始されてないデバイスからRAIDセットを構築して開始する。

    • int count_devices(struct lib_context *lc, enum dev_type type)

      DEVICE, RAIDといった指定されたタイプのdiscover_devices()およびdiscover_raid_devices()によって検出したデバイスの数を返す。

    • int perform(struct lib_context *lc, char **argv)

      パラメータで指定された様々なアクションを実効して成功した場合、0以外を返す。例えば、RAIDセットの開始、停止、プロパティの表示などを行う。

  • 開始(その1)

    ツールでは、RAIDセットの詳細な組み立てを隠す、次の上位レベルの関数を呼ぶ。

    • int group_set(struct lib_context *lc, char *name)

      RAIDセットのグループ化に成功した場合、0以外を返す。

  • 開始(その2+3)

    – セット・チェック結果が無効かエラーがある、RAID1以外のデバイスは開始しない。

    – セット中のRAIDデバイスのリストを繰り返したどって、ASCIIのdmマッピング・テーブルを作成する。また、SPAN等の種別、デバイスパス、デバイスへのオフセットやマップの大きさ、およびRAIDの場合のストライプサイズといったレイアウト情報を読み出す。

    – ユニークなデバイス名を作成する。

    – マップされたデバイスを作成して、マップ用テーブルをロードするために次の関数を使用して、Device-mapperライブラリを呼び出す。

    • int activate_set(struct lib_context *lc, void *rs)

      RAIDセットの開始に成功した場合、0以外を返す。

  • 開始(その4)

    – MSDOSパーティションが構成するRAIDセットを開始する。

  • 停止

    – まず、パーティションを構成するRAIDセットが動作中か停止しているかを検出。

    – RAIDセットが動作中かどうかチェックして、マップされたデバイス(デバイスが階層的にマップされている場合は再帰的に)を削除するために、デバイス・マッパ・ライブラリを呼出す。

    • int deactivate_set(struct lib_context *lc, void *rs)

      RAIDセットの停止に成功した場合、0以外を返す。

  • 表示

    – 検出した全てのブロックデバイスの一覧

    – 活動している(または停止している)RAIDデバイスの一覧

    – 全ての、または特定のRAIDデバイスのプロパティ(メンバセットを構成するブロックデバイス名とそれらがマップされている、オフセット、領域サイズなど)の表示

    • void display_devices(struct lib_context *lc, enum dev_type type)

      DEVICE, RAIDといった’type’で指定された型のデバイスを表示。

    • void display_set(struct lib_context *lc, void *rs, enum active_type type, int top)

      ACTIVE, INACTIVE, ALLといった’type’で指定された状態のRAIDセットを表示。

ソースコードのディレクトリ・ツリー

dmraid —/doc
	+-/include
	+-/lib —/activate
	|	|-/datastruct
	|	|-/device
	|	|-/display
	|	|-/format —/ataraid
	|	|	   +-/partition
	|	|          +-/template
	|	|-/locking
	|	|-/log
	|	|-/misc
	|	|-/metadata
	|	+-/mm
	+-/man
	+-/tools

将来の拡張

  • インディスク・メタデータを更新するための書込みサポートを拡張する。
    • メタデータのバックアップから復元するため
    • ディスクの故障を記録するため
  • (例えばセクタエラーのような)標準規格/ベンダ固有オンディスク・ログ状態のロギングのサポート。
  • RAIDセットの健全性(ディスク・フェイル、ホットスペア、リビルド等)をモニタする状態デーモンと、CLI(Command Line Interface)のフロントエンド。

未解決な疑問

  • いくつかのATARAIDフォーマットをサポートするRAID3+5のような、より高いRAIDレベルのDevice-mapperターゲット上で優先順位を付けて動作させる必要があるか?