# 通知設計書 2-DEV DESTROY

## 概要

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

### 本通知の処理概要

GEOMフレームワークのDEVクラスがデバイスを破棄する際に、devctlサブシステムを通じてユーザランドに通知を送信する処理である。

**業務上の目的・背景**：ストレージデバイスが取り外された場合やGEOMプロバイダが消滅した場合に、ユーザランドのデーモン（devd等）がデバイスの消失を検知する必要がある。これにより自動アンマウント処理やリソース解放、ユーザへの警告表示などの自動化が可能になる。

**通知の送信タイミング**：g_dev_destroy()関数内で、GEOMコンシューマのデタッチ・破棄処理の直前に送信される。具体的にはコンシューマのアクセスカウントを解放し、g_detach()を呼ぶ前の段階で通知が発行される。

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

**通知内容の概要**：破棄されるcdevのデバイス名が「cdev=デバイス名」形式で通知される。

**期待されるアクション**：受信したデーモンは、当該デバイスに関連するマウントの解除、ダンプデバイス設定のクリア、関連リソースの解放などを実行する。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

devctl_notify()により/dev/devctlデバイスのイベントキューに格納される。全リスナーにブロードキャストされる。

## 通知テンプレート

### devctl通知メッセージ

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

### 本文テンプレート

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

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| cdev | 破棄されるデバイスのデバイス名 | gp->name（GEOMジオメトリ名） | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| カーネル内部イベント | g_dev_destroy()実行 | GEOMトポロジロック保持中 | プロバイダのorphan化やデバイス消失時に呼ばれる |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| なし | g_dev_destroy()が呼ばれた場合は常に通知が発行される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[プロバイダorphan発生] --> B[g_dev_orphan呼出]
    B --> C[delist_dev / destroy_dev_sched_cb]
    C --> D[g_dev_callback]
    D --> E{未処理リクエストあり?}
    E -->|あり| F[g_dev_doneで完了を待つ]
    E -->|なし| G[g_post_event g_dev_destroy]
    F --> G
    G --> H[g_dev_destroy実行]
    H --> I[snprintf buf cdev=name]
    I --> J[devctl_notify GEOM DEV DESTROY buf]
    J --> K[knlist_clear / knlist_destroy]
    K --> L[g_access解放]
    L --> M[g_detach / g_destroy_consumer]
    M --> N[g_destroy_geom]
    N --> O[終了]
```

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

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

| データ構造 | 用途 | 備考 |
|-----------|------|------|
| struct g_consumer | GEOMコンシューマ | cp->geom->nameからデバイス名を取得 |
| struct g_geom | GEOMジオメトリ | gp->nameがデバイス名 |
| struct g_dev_softc | DEVクラスのソフト状態 | sc_activeフラグでリクエスト完了を追跡 |

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| なし | g_dev_destroy()はvoid関数であり、エラーは発生しない | N/A |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし

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

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

## 備考

- g_dev_destroy()はg_post_event()経由で呼ばれるため、GEOMイベントスレッドで実行される
- SC_A_DESTROYフラグ（1 << 31）はデバイス破棄がスケジュールされたことを示す
- 未完了のI/Oリクエストがある場合、g_dev_done()で最後のリクエストが完了した時点でg_dev_destroy()がスケジュールされる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | geom_dev.c | `sys/geom/geom_dev.c` | g_dev_softc構造体（行60-70）：SC_A_DESTROYフラグ（行67）の意味 |

**読解のコツ**: sc_activeフィールドはビットフラグとカウンタの複合で、上位ビットが状態フラグ、下位ビットがアクティブI/Oカウンタとなっている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | geom_dev.c | `sys/geom/geom_dev.c` | g_dev_orphan()関数（行850-876）：デバイス消失の起点 |
| 2-2 | geom_dev.c | `sys/geom/geom_dev.c` | g_dev_callback()関数（行822-838）：非同期破棄コールバック |

**主要処理フロー**:
1. **行858**: sc = cp->privateでソフト状態を取得
2. **行865-871**: ダンプデバイス設定をリセット
3. **行874**: delist_dev()でdevfsからデバイスを削除
4. **行875**: destroy_dev_sched_cb()でg_dev_callbackをスケジュール

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | geom_dev.c | `sys/geom/geom_dev.c` | g_dev_destroy()関数（行213-237）：通知発行とリソース解放 |

**主要処理フロー**:
- **行226**: snprintf(buf, sizeof(buf), "cdev=%s", gp->name)でバッファ構築
- **行227**: devctl_notify("GEOM", "DEV", "DESTROY", buf)で通知発行
- **行228-236**: knlist解放、g_access解放、g_detach、g_destroy_consumer、g_destroy_geom

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

```
[プロバイダorphan]
    |
    +-- g_dev_orphan() [sys/geom/geom_dev.c:850]
            |
            +-- delist_dev() [sys/kern/kern_conf.c:1224]
            +-- destroy_dev_sched_cb(dev, g_dev_callback, cp) [sys/kern/kern_conf.c:1516]
                    |
                    +-- g_dev_callback() [sys/geom/geom_dev.c:822]
                            |
                            +-- g_post_event(g_dev_destroy, ...) [GEOMフレームワーク]
                                    |
                                    +-- g_dev_destroy() [sys/geom/geom_dev.c:213]
                                            |
                                            +-- devctl_notify("GEOM","DEV","DESTROY",...) [行227]
                                            +-- knlist_clear() / knlist_destroy()
                                            +-- g_access() [アクセス解放]
                                            +-- g_detach()
                                            +-- g_destroy_consumer()
                                            +-- g_destroy_geom()
```

### データフロー図

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

プロバイダorphanイベント  --->  g_dev_orphan()              --->  delist_dev (devfs削除)
                                    |
                                    v
                              g_dev_callback()              --->  SC_A_DESTROY設定
                                    |
                                    v
                              g_dev_destroy()               --->  devctl_notify()
                                    |                               |
                                    v                               v
                              GEOMリソース解放               /dev/devctl (イベントキュー)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| geom_dev.c | `sys/geom/geom_dev.c` | ソース | g_dev_destroy()でDESTROY通知を発行 |
| kern_conf.c | `sys/kern/kern_conf.c` | ソース | destroy_dev_sched_cb()の実装 |
| devctl.h | `sys/sys/devctl.h` | ヘッダ | devctl_notify()のプロトタイプ |
| subr_bus.c | `sys/kern/subr_bus.c` | ソース | devctl_notify()の実装 |
