# 機能設計書 21-devfs

## 概要

本ドキュメントは、FreeBSDのdevfs（デバイスファイルシステム）の機能設計を記述する。devfsはデバイスファイルを動的に管理する擬似ファイルシステムであり、カーネルがデバイスの登録・削除に応じて `/dev` ディレクトリの内容を自動的に更新する機構を提供する。

### 本機能の処理概要

**業務上の目的・背景**：従来の静的な `/dev` ディレクトリでは、デバイスの追加・削除に対して手動でデバイスノードを作成・削除する必要があった。devfsはカーネルが認識するデバイスドライバの登録情報に基づき、デバイスノードを動的に生成・管理することで、常に実際のハードウェア構成と `/dev` の内容を一致させる。jailやコンテナ環境ではルールセットを用いてデバイスの可視性を制御する。

**機能の利用シーン**：システム起動時の `/dev` マウント、デバイスドライバのロード・アンロード時のデバイスノード自動生成・削除、jail環境でのデバイスアクセス制御、devfs.rulesによるパーミッション・所有者の一括設定。

**主要な処理内容**：
1. devfsファイルシステムのマウント・アンマウント（devfs_mount / devfs_unmount）
2. デバイスノード（devfs_dirent）の動的生成・削除・管理
3. ルールセットによるデバイスノードの属性変更（所有者、パーミッション、表示/非表示）
4. vnode操作（lookup, readdir, open, close, read, write等）の提供
5. jail環境向けのルールセット強制適用

**関連システム・外部連携**：カーネルデバイスドライバフレームワーク（cdev/cdevsw）、jail、MACフレームワーク

**権限による制御**：jail内ではprison構造体のpr_devfs_rsnumで指定されたルールセットが強制適用される。ルールセットの変更にはPRIV_DEVFS_RULE権限が必要。

## 関連画面

本機能はカーネル内部のファイルシステムであり、直接的に関連するUI画面は存在しない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | - |

## 機能種別

ファイルシステム操作（擬似ファイルシステム管理）/ デバイスノード動的生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| from | char* | No | マウント元（常に"devfs"） | 文字列チェック |
| ruleset | int | No | 適用するルールセット番号 | 0-65535の範囲 |
| export | - | No | エクスポートオプション（非サポート） | EOPNOTSUPPを返却 |

### 入力データソース

- カーネル内部のcdev_priv_list（デバイスドライバ登録リスト）
- マウントオプション（vfs_mount_opt構造体）
- ルール定義（devfs_rule構造体、ioctlインタフェース経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| デバイスノード | devfs_dirent | /dev配下のデバイスファイルエントリ |
| statfs情報 | struct statfs | ファイルシステム統計情報（ブロックサイズ512、ブロック数2等） |

### 出力先

- VFSレイヤ経由でユーザ空間の `/dev` ディレクトリとして公開
- stat(2), readdir(2)等のシステムコール応答

## 処理フロー

### 処理シーケンス

```
1. devfs_mount()
   └─ devfs_mount構造体の割り当て・初期化
      ├─ dm_idxのユニーク番号割り当て（alloc_unr）
      ├─ dm_lockの初期化（sx_init）
      ├─ ルートディレクトリ作成（devfs_vmkdir）
      └─ ルールセット設定（jail環境では強制）
2. デバイスアクセス時（devfs_vnops）
   └─ devfs_lookup → devfs_populate → デバイスノード検索
3. デバイス登録時
   └─ devfs_devs.c内の処理 → cdevp_listへの登録 → generation番号更新
4. devfs_populate()
   └─ generation番号比較 → 差分のdevfs_dirent生成・削除
5. devfs_unmount()
   └─ vflush → devfs_cleanup → devfs_rules_cleanup → リソース解放
```

### フローチャート

```mermaid
flowchart TD
    A[mount devfs] --> B[devfs_mount構造体割り当て]
    B --> C[ルートディレクトリ作成]
    C --> D{ルールセット指定?}
    D -->|Yes| E[ルールセット設定]
    D -->|No| F[マウント完了]
    E --> F
    F --> G[デバイスアクセス]
    G --> H{populate必要?}
    H -->|Yes| I[devfs_populate: cdevp_listと同期]
    H -->|No| J[vnodeオペレーション実行]
    I --> J
    J --> K[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-21-01 | jail内ルールセット強制 | jail環境ではprison構造体のpr_devfs_rsnumが強制適用される | injail(td->td_ucred)がtrueの場合 |
| BR-21-02 | ルールセット0は空集合 | ルールセット0はNULL（空）ルールセットとして扱い変更不可 | 常時 |
| BR-21-03 | MNT_ROOTFS非サポート | devfsはルートファイルシステムとしてマウント不可 | MNT_ROOTFSフラグ指定時 |
| BR-21-04 | ルール深度制限 | ルールセットのインクルード深度はdevfs_rule_depth（デフォルト1）で制限 | ルール適用時 |

### 計算ロジック

ルールIDはルールセット番号（上位16ビット）とルール番号（下位16ビット）を組み合わせて生成: `rid = rn | (rsn << 16)`

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

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

本機能はファイルシステムベースであり、RDBMS操作は行わない。カーネル内メモリ上のデータ構造を直接操作する。

| 操作 | 対象データ構造 | 操作種別 | 概要 |
|-----|-------------|---------|------|
| マウント | devfs_mount | CREATE | マウントポイント構造体の生成 |
| デバイス同期 | devfs_dirent | CREATE/DELETE | cdevp_listとの差分同期 |
| ルール適用 | devfs_krule | READ/UPDATE | ルールの照合と属性変更 |

### テーブル別操作詳細

#### devfs_dirent（メモリ内データ構造）

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| CREATE | de_mode, de_uid, de_gid | デバイスドライバのデフォルト値、ルール適用後の値 | devfs_newdirent |
| UPDATE | de_flags | DE_WHITEOUT（非表示）等 | ルール適用時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EOPNOTSUPP | 非サポート | MNT_ROOTFSまたはexportオプション指定時 | マウントオプションを修正 |
| EINVAL | 不正パラメータ | 無効なマウントオプションまたはルールセット番号 | 0-65535の範囲で指定 |
| EPERM | 権限不足 | jail内で許可されていないルールセット指定 | prison設定を確認 |
| ESRCH | 検索失敗 | 指定されたルールセットが存在しない | ルールセットを事前に作成 |

### リトライ仕様

devfsはカーネル内部処理であり、リトライはシステムコールの再発行で対応する。

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

devfs_mount構造体のdm_lock（sx_lock）により排他制御を行う。マウント・アンマウント・ルール操作は排他ロック（sx_xlock）下で実行される。populate処理もdm_lockで保護される。

## パフォーマンス要件

devfsは擬似ファイルシステムであり、全データがメモリ上に存在するため、ディスクI/Oは発生しない。デバイス一覧の同期はgeneration番号の比較により差分検出を行うため、変更がない場合のオーバーヘッドは最小限。

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

- ルールセットによるデバイスノードの表示/非表示制御（jail向け）
- uid/gid/modeの強制設定によるデバイスアクセス制御
- MACフレームワークとの統合（MAC_MULTILABEL対応）
- PRIV_DEVFS_RULE権限によるルール操作の制限

## 備考

- devfsはVFCF_SYNTHETICおよびVFCF_JAILフラグで登録されており、jail内での使用が前提として設計されている
- sbin/devfsユーザランドコマンドでルールの管理が可能

---

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

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

### 推奨読解順序

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

devfsの中核となるデータ構造を理解することが最優先。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | devfs.h | `sys/fs/devfs/devfs.h` | devfs_rule（66-100行目）、devfs_dirent（129-155行目）、devfs_mount（160-168行目）の3つの主要構造体 |
| 1-2 | devfs_int.h | `sys/fs/devfs/devfs_int.h` | cdev_priv構造体、カーネル内部のデバイス管理構造 |

**読解のコツ**: devfs_direntはVFS上のディレクトリエントリに対応し、devfs_mountはマウントポイント毎のインスタンスを表す。de_flagsのDE_WHITEOUTがルールによるデバイス非表示の実装。

#### Step 2: エントリーポイントを理解する

VFS操作のエントリーポイントであるvfsopsを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | devfs_vfsops.c | `sys/fs/devfs/devfs_vfsops.c` | マウント/アンマウント/root/statfsの4つのVFS操作 |

**主要処理フロー**:
1. **65-161行目**: devfs_mount() - マウント処理全体。jail判定（83行目）、ルールセット解析（92-98行目）、devfs_mount構造体割り当て（122行目）、ルートディレクトリ作成（139行目）
2. **170-200行目**: devfs_unmount() - アンマウント処理。vflush（185行目）、devfs_cleanup（189行目）、devfs_rules_cleanup（190行目）
3. **236-244行目**: VFS操作テーブルの定義とVFS_SET登録

#### Step 3: デバイスノード管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | devfs_devs.c | `sys/fs/devfs/devfs_devs.c` | cdevp_list（55行目）グローバルデバイスリスト、generation番号管理（66-68行目）、sysctl_devname（78行目） |

**主要処理フロー**:
- **55行目**: cdevp_list - 全アクティブデバイスのマスターリスト
- **66-68行目**: devfs_generation - デバイス変更検出用のgeneration番号
- **70-72行目**: devfs_rule_depth - ルールセットのインクルード深度制限

#### Step 4: ルールセットサブシステムを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | devfs_rule.c | `sys/fs/devfs/devfs_rule.c` | devfs_krule（82-86行目）カーネル内ルール表現、devfs_ruleset（94-99行目）ルールセット管理構造 |

**読解のコツ**: ルールの「apply」と「run」の違いに注意（29-34行目のコメント）。applyは条件判定を含み、runは無条件実行。

#### Step 5: vnodeオペレーションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | devfs_vnops.c | `sys/fs/devfs/devfs_vnops.c` | devfs_vnodeops/devfs_specops（67-68行目）、devfs_timestamp（97-99行目） |
| 5-2 | devfs_dir.c | `sys/fs/devfs/devfs_dir.c` | ディレクトリ操作の実装 |

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

```
mount(2) "devfs"
    |
    +-- devfs_mount() [devfs_vfsops.c:65]
    |       +-- alloc_unr() : ユニークID割当
    |       +-- devfs_vmkdir() : ルートディレクトリ生成
    |       +-- devfs_ruleset_set() : ルールセット設定
    |       +-- devfs_ruleset_apply() : ルール適用
    |
    +-- devfs_root() [devfs_vfsops.c:204]
    |       +-- devfs_allocv() : vnode割当
    |
    +-- open/read/lookup [devfs_vnops.c]
    |       +-- devfs_populate() : デバイスリスト同期
    |       |       +-- cdevp_list走査
    |       |       +-- devfs_newdirent() : 新規ノード生成
    |       +-- devfs_rules_apply() : ルール適用
    |
    +-- devfs_unmount() [devfs_vfsops.c:170]
            +-- vflush() : vnode解放
            +-- devfs_cleanup() : dirent解放
            +-- devfs_rules_cleanup() : ルール解放
```

### データフロー図

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

cdevp_list        ───▶ devfs_populate()          ───▶ devfs_dirent
(カーネルデバイス一覧)      (差分同期)                    (デバイスノード)
                                                           │
devfs_rule        ───▶ devfs_rules_apply()       ───▶     │
(ルール定義)              (属性変更/表示制御)               │
                                                           ▼
mount opts        ───▶ devfs_mount()             ───▶ /dev (VFS)
(マウントオプション)       (FS初期化)                  (ユーザ空間公開)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| devfs.h | `sys/fs/devfs/devfs.h` | ヘッダ | 主要データ構造・API定義 |
| devfs_int.h | `sys/fs/devfs/devfs_int.h` | ヘッダ | カーネル内部データ構造 |
| devfs_vfsops.c | `sys/fs/devfs/devfs_vfsops.c` | ソース | VFS操作（mount/unmount/root/statfs） |
| devfs_vnops.c | `sys/fs/devfs/devfs_vnops.c` | ソース | vnodeオペレーション（lookup/readdir/open等） |
| devfs_devs.c | `sys/fs/devfs/devfs_devs.c` | ソース | デバイスノード管理・generation番号管理 |
| devfs_rule.c | `sys/fs/devfs/devfs_rule.c` | ソース | ルールセットサブシステム |
| devfs_dir.c | `sys/fs/devfs/devfs_dir.c` | ソース | ディレクトリ操作 |
