# 機能設計書 32-mdデバイス（メモリディスク）

## 概要

本ドキュメントは、FreeBSDにおけるメモリ上に仮想ディスクを作成する機構（md(4)デバイス）の管理コマンドであるmdconfigおよびmdmfsの機能設計書である。

### 本機能の処理概要

mdconfigはメモリベースの仮想ブロックデバイス（md(4)）の作成・削除・リサイズ・一覧表示を行うユーティリティである。mdmfsはmdconfig, newfs, mountを連携して呼び出し、メモリディスクの作成からファイルシステム構築・マウントまでを一括で行うラッパーコマンドである。

**業務上の目的・背景**：テスト環境の構築、一時的な高速ストレージ領域の確保、ディスクイメージのマウント、組み込みシステムのRAMディスク作成など、メモリ上に仮想的なブロックデバイスを必要とするさまざまなユースケースに対応する。

**機能の利用シーン**：tmpfsの代替としてUFSファイルシステムが必要な場合、ISOイメージやディスクイメージファイルのループバックマウント、ビルド時の高速作業ディレクトリの作成、テスト用パーティションの作成などで利用される。

**主要な処理内容**：
1. メモリディスクのアタッチ（作成） - malloc, vnode, swap, nullの4タイプ対応
2. メモリディスクのデタッチ（削除）
3. メモリディスクのリサイズ
4. メモリディスクの一覧表示・クエリ
5. mdmfsによるメモリディスク作成+newfs+mount一括処理
6. tmpfsへの自動フォールバック（mdmfs "auto"モード）

**関連システム・外部連携**：GEOMフレームワーク（geom_mdカーネルモジュール）、newfs(8)、mount(8)、tmpfs

**権限による制御**：/dev/mdctlデバイスファイルへのアクセス権限に基づく。通常root権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | CLIツールのため該当する画面なし |

## 機能種別

デバイス管理（CRUD操作 - 仮想ディスクの作成・削除・リサイズ・一覧表示）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -a | flag | 条件付 | アタッチ（作成）モード | -d, -r, -lと排他 |
| -d | flag | 条件付 | デタッチ（削除）モード | -a, -r, -lと排他 |
| -r | flag | 条件付 | リサイズモード | -a, -d, -lと排他 |
| -l | flag | 条件付 | 一覧表示モード | -a, -d, -rと排他 |
| -t type | string | -a時必須 | タイプ（malloc/vnode/swap/null） | 指定タイプのいずれかに一致 |
| -f file | string | vnode時必須 | バッキングファイルパス | 実在する通常ファイル |
| -s size | string | malloc/swap/null時必須 | ディスクサイズ | 数値+サフィックス(b/k/m/g/t/p) |
| -u unit | string | -d/-r時必須 | ユニット番号 | 有効なユニット番号 |
| -S sectorsize | ulong | No | セクターサイズ | 正の整数 |
| -L label | string | No | ディスクラベル | PATH_MAX以内 |
| -o option | string | No | オプション（async,cache,compress等） | 有効なオプション名 |
| -n | flag | No | ユニット番号のみ出力 | - |
| -v | flag | No | 詳細表示（-l時のみ） | - |

### 入力データソース

コマンドライン引数、バッキングファイル（vnodeタイプ時）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ユニット名 | string | 作成されたmdデバイス名（例: md0） |
| デバイス一覧 | text | md一覧（タイプ、サイズ、ファイル、ラベル、オプション） |
| 終了コード | int | 0=成功, 1=失敗 |

### 出力先

標準出力、/dev/mdXデバイスファイルの作成

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数をgetoptで解析
   └─ アクション（ATTACH/DETACH/RESIZE/LIST）を決定
2. geom_mdカーネルモジュールのロード確認
   └─ kld_isloaded("g_md")で確認、未ロードならkld_load("geom_md")
3. /dev/mdctlデバイスをO_RDWRでオープン
4. アクションに応じたioctlを実行
   └─ ATTACH: MDIOCATTACH
   └─ DETACH: MDIOCDETACH
   └─ RESIZE: MDIOCRESIZE
   └─ LIST: GEOMライブラリで一覧取得
5. 結果を出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[引数解析]
    B --> C{アクション判定}
    C -->|ATTACH| D[geom_mdモジュールロード確認]
    C -->|DETACH| D
    C -->|RESIZE| D
    C -->|LIST| G[geom_gettree + geom_stats]
    D --> E[/dev/mdctl オープン]
    E --> F{アクション実行}
    F -->|ATTACH| F1[ioctl MDIOCATTACH]
    F -->|DETACH| F2[ioctl MDIOCDETACH]
    F -->|RESIZE| F3[ioctl MDIOCRESIZE]
    F1 --> H[ユニット番号出力]
    F2 --> I[終了]
    F3 --> I
    G --> J[MD一覧表示]
    H --> I
    J --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-32-01 | タイプ推論 | -tが省略された場合、-fがあればvnode、-sがあればswapと推論する | ATTACH時に-t未指定 |
| BR-32-02 | 読み取り専用自動設定 | vnodeタイプでバッキングファイルが書き込み不可の場合、自動的にreadonlyオプションを設定 | ATTACH時 vnodeタイプ |
| BR-32-03 | autoユニット | -uが未指定の場合、MD_AUTOUNITフラグにより自動でユニット番号が割り当てられる | ATTACH時 |
| BR-32-04 | mdmfs autoモード | "auto"指定時、tmpfsが利用可能であればtmpfsを使用し、不可能ならmdを使用する | mdmfsのmd-device引数が"auto" |

### 計算ロジック

サイズ引数の解析: サフィックスなし=512バイトブロック数, b=バイト, k=KiB, m=MiB, g=GiB, t=TiB, p=PiB

## データベース操作仕様

該当なし（カーネルデバイスドライバとのioctl通信）

### 操作別データベース影響一覧

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 引数エラー | 排他的なフラグの同時指定 | usage表示 |
| 1 | モジュールエラー | geom_mdモジュールのロード失敗 | カーネル構成を確認 |
| 1 | デバイスエラー | /dev/mdctlのオープン失敗 | 権限確認 |
| 1 | ioctlエラー | MDIOCATTACH/DETACH/RESIZE失敗 | デバイス状態確認 |

### リトライ仕様

明示的なリトライ機構はない。

## トランザクション仕様

各ioctl呼び出しはアトミック。mdmfsの場合、mdconfig→newfs→mountの3段階で実行され、途中で失敗した場合のロールバックは行われない。

## パフォーマンス要件

メモリディスクの性能はバッキングストアのタイプに依存する。mallocタイプはカーネルmallocから割り当て、swapタイプはスワップ空間を使用する。

## セキュリティ考慮事項

- /dev/mdctlへのアクセスにはroot権限が必要
- swapタイプのメモリディスクは初期化時にゼロクリアされる
- compressオプションはゼロページの圧縮を行いメモリ使用量を削減

## 備考

mdmfsはmount_mfsの後継であり、互換性のためmount_mfsとして起動された場合は互換動作モードとなる。

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | mdioctl.h | `sys/sys/mdioctl.h` | struct md_ioctl（アタッチ・デタッチ等のioctl引数）、md_types列挙型、MDオプションフラグ |

**読解のコツ**: md_ioctl構造体のmd_type, md_options, md_mediasizeフィールドがデバイス作成時の主要パラメータである。

#### Step 2: mdconfigのメインフローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | mdconfig.c | `sbin/mdconfig/mdconfig.c` | main()関数のgetoptループと4つのアクション分岐 |

**主要処理フロー**:
1. **58行目**: action列挙型（UNSET, ATTACH, DETACH, RESIZE, LIST）
2. **99-408行目**: main()関数 - getoptループ(118-274行目)でオプション解析、370-371行目でgeom_mdモジュールロード、377-405行目でアクション実行
3. **466-484行目**: md_set_file() - vnodeタイプのバッキングファイル設定
4. **492-593行目**: md_list() - GEOMライブラリを使用したmdデバイス一覧取得

#### Step 3: mdmfsのワークフローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | mdmfs.c | `sbin/mdmfs/mdmfs.c` | main()関数のauto/tmpfs/md分岐、ヘルパープログラム呼び出し |

**主要処理フロー**:
- **95-367行目**: main() - getoptループ(143-256行目)、サイズ解析(270-299行目)、auto/tmpfs/md分岐(310-361行目)
- **418-442行目**: do_mdconfig_attach() - mdconfigコマンド呼び出しによるデバイス作成
- **610-619行目**: do_newfs() - newfsコマンド呼び出しによるファイルシステム作成
- **522-532行目**: do_mount_md() - mountコマンド呼び出しによるマウント

### プログラム呼び出し階層図

```
mdconfig main() [mdconfig.c:99]
    |
    +-- getopt解析 [118-274行目]
    +-- kld_isloaded("g_md") / kld_load("geom_md") [370-371行目]
    +-- open(/dev/mdctl, O_RDWR) [373行目]
    +-- ioctl(MDIOCATTACH/MDIOCDETACH/MDIOCRESIZE) [378-394行目]
    +-- md_list() [492行目]
            +-- geom_gettree()
            +-- geom_stats_open()
            +-- geom_stats_snapshot_get/next()

mdmfs main() [mdmfs.c:95]
    |
    +-- getopt解析 [143-256行目]
    +-- auto/tmpfs/md分岐 [310-361行目]
    |
    +-- [mdの場合]
    |   +-- do_mdconfig_attach/attach_au() [418/447行目]
    |   |       +-- run(mdconfig -a -t ...)
    |   +-- do_newfs() [610行目]
    |   |       +-- run(newfs ...)
    |   +-- do_mount_md() [522行目]
    |           +-- run(mount ...)
    |
    +-- [tmpfsの場合]
    |   +-- do_mount_tmpfs() [537行目]
    |           +-- run(mount -t tmpfs ...)
    |
    +-- do_mtptsetup() [551行目]
    +-- do_copy() [625行目] (skelオプション時)
```

### データフロー図

```
[入力]                    [処理]                         [出力]

コマンドライン引数 ──> getopt解析
                          |
バッキングファイル ──> md_set_file()
                          |
                     ioctl(MDIOCATTACH)
                          |
                     カーネル md(4) ドライバ
                          |
                     GEOM フレームワーク ──> /dev/mdX デバイスファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| mdconfig.c | `sbin/mdconfig/mdconfig.c` | ソース | mdconfigメイン処理 |
| mdconfig.8 | `sbin/mdconfig/mdconfig.8` | manページ | mdconfigマニュアル |
| mdmfs.c | `sbin/mdmfs/mdmfs.c` | ソース | mdmfsメイン処理 |
| mdmfs.8 | `sbin/mdmfs/mdmfs.8` | manページ | mdmfsマニュアル |
| mdioctl.h | `sys/sys/mdioctl.h` | ヘッダ | md ioctl定義 |
| md.c | `sys/dev/md/md.c` | ソース | mdカーネルドライバ |
