# 通知設計書 3-DEV MEDIACHANGE

## 概要

本ドキュメントは、FreeBSDカーネルのGEOMフレームワークにおいて、ディスクメディアが変更された際に発行されるdevctl通知「GEOM DEV MEDIACHANGE」の設計を記述する。

### 本通知の処理概要

GEOMプロバイダの「GEOM::media」属性が変更された際に、DEVクラスのattrchangedコールバック経由でg_dev_set_media()が呼ばれ、devctlサブシステムを通じてユーザランドに通知を送信する処理である。

**業務上の目的・背景**：リムーバブルメディア（CD/DVD、USBメモリなど）の挿入・交換時に、ユーザランドが新しいメディアの存在を検知し、自動マウントやメディア認識処理を実行するために本通知が必要となる。また、ディスクのメディアサイズやジオメトリが変更された場合にも通知される。

**通知の送信タイミング**：GEOMプロバイダの「GEOM::media」属性が変更された時点で送信される。具体的にはg_dev_attrchanged()コールバックが"GEOM::media"属性で呼ばれた際にg_dev_set_media()が実行される。

**通知の受信者**：devd(8)デーモンおよび/dev/devctlをモニタリングしているユーザランドプロセスが受信する。

**通知内容の概要**：メディア変更が発生したcdevのデバイス名が「cdev=デバイス名」形式で通知される。

**期待されるアクション**：受信したデーモンは、メディアの再認識、自動マウント、パーティションテーブルの再読み込みなどを実行する。

## 通知種別

カーネル内devctl通知（/dev/devctl経由のユーザランド通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（devctlキューへのエンキュー） |
| 優先度 | 通常 |
| リトライ | なし |

### 送信先決定ロジック

devctl_notify()により全リスナーにブロードキャストされる。

## 通知テンプレート

### devctl通知メッセージ

| 項目 | 内容 |
|-----|------|
| system | `GEOM` |
| subsystem | `DEV` |
| type | `MEDIACHANGE` |
| data | `cdev=<デバイス名>` |

### 本文テンプレート

```
!system=GEOM subsystem=DEV type=MEDIACHANGE cdev=<デバイス名>
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| cdev | メディア変更が発生したデバイスのデバイス名 | dev->si_name（sc->sc_devまたはsc->sc_alias） | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| カーネル内部イベント | GEOM::media属性変更 | g_dev_attrchanged()がattr=="GEOM::media"で呼ばれた場合 | メインデバイスとエイリアスデバイスの両方に通知 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| sc->sc_alias == NULL | エイリアスデバイスが存在しない場合、エイリアス分の通知は発行されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[GEOM::media属性変更] --> B[g_dev_attrchanged呼出]
    B --> C{attr == GEOM::media ?}
    C -->|Yes| D[g_dev_set_media呼出]
    C -->|No| E[他の属性処理]
    D --> F[sc->sc_devのsi_nameでbuf構築]
    F --> G[devctl_notify DEVFS CDEV MEDIACHANGE]
    G --> H[devctl_notify GEOM DEV MEDIACHANGE]
    H --> I{sc->sc_alias != NULL ?}
    I -->|Yes| J[sc->sc_aliasのsi_nameでbuf構築]
    J --> K[devctl_notify DEVFS CDEV MEDIACHANGE エイリアス]
    K --> L[devctl_notify GEOM DEV MEDIACHANGE エイリアス]
    L --> M[終了]
    I -->|No| M
```

## データベース参照・更新仕様

### カーネル内データ構造

| データ構造 | 用途 | 備考 |
|-----------|------|------|
| struct g_dev_softc | DEVクラスのソフト状態 | sc_devとsc_aliasの両方を参照 |
| struct cdev | キャラクタデバイス | si_nameからデバイス名を取得 |

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| なし | g_dev_set_media()はvoid関数 | N/A |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし

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

- /dev/devctlへのアクセスにはroot権限が必要
- 通知に含まれるデバイス名はcdev名のみ

## 備考

- g_dev_set_media()は同時にDEVFS CDEV MEDIACHANGEとGEOM DEV MEDIACHANGEの2つの通知を発行する（No.6のCDEV MEDIACHANGE通知と連動）
- エイリアスデバイスが存在する場合、エイリアスに対しても同じ2つの通知が発行される（合計最大4つの通知）
- メディア変更はdisk_media_changed()→g_media_changed()→g_attr_changed()→g_dev_attrchanged()の経路で伝播する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | geom_dev.c | `sys/geom/geom_dev.c` | g_dev_softc構造体（行60-70）：sc_devとsc_aliasフィールド |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | geom_dev.c | `sys/geom/geom_dev.c` | g_dev_attrchanged()関数（行303-316）：属性変更のディスパッチ |

**主要処理フロー**:
1. **行307**: attr == "GEOM::media"の場合にg_dev_set_media()を呼出
2. **行312**: attr == "GEOM::physpath"の場合にg_dev_set_physpath()を呼出

#### Step 3: MEDIACHANGE通知発行処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | geom_dev.c | `sys/geom/geom_dev.c` | g_dev_set_media()関数（行283-301）：通知発行処理 |

**主要処理フロー**:
- **行292**: snprintf(buf, sizeof(buf), "cdev=%s", dev->si_name)
- **行293**: devctl_notify("DEVFS", "CDEV", "MEDIACHANGE", buf)
- **行294**: devctl_notify("GEOM", "DEV", "MEDIACHANGE", buf)
- **行295-300**: エイリアスデバイスに対しても同様の処理

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

```
g_dev_attrchanged(cp, "GEOM::media") [sys/geom/geom_dev.c:303]
    |
    +-- g_dev_set_media(cp) [sys/geom/geom_dev.c:283]
            |
            +-- devctl_notify("DEVFS", "CDEV", "MEDIACHANGE", buf) [行293]
            +-- devctl_notify("GEOM", "DEV", "MEDIACHANGE", buf) [行294]
            |
            +-- [エイリアスデバイスが存在する場合]
                    +-- devctl_notify("DEVFS", "CDEV", "MEDIACHANGE", buf) [行298]
                    +-- devctl_notify("GEOM", "DEV", "MEDIACHANGE", buf) [行299]
```

### データフロー図

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

GEOM::media属性変更      --->  g_dev_attrchanged()          --->  g_dev_set_media()
                                                                      |
                                                                      +-- DEVFS CDEV MEDIACHANGE
                                                                      +-- GEOM DEV MEDIACHANGE
                                                                      |
                                                              /dev/devctl (イベントキュー)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| geom_dev.c | `sys/geom/geom_dev.c` | ソース | g_dev_set_media()でMEDIACHANGE通知を発行 |
| geom_disk.c | `sys/geom/geom_disk.c` | ソース | disk_media_changed()がメディア変更の上位エントリーポイント |
| devctl.h | `sys/sys/devctl.h` | ヘッダ | devctl_notify()のプロトタイプ |
| subr_bus.c | `sys/kern/subr_bus.c` | ソース | devctl_notify()の実装 |
