# 通知設計書 5-disk属性変更

## 概要

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

### 本通知の処理概要

GEOM diskクラスにおいて、ディスクの属性（GEOM::physpath、GEOM::ident等）が変更された際に、disk_attr_changed()関数を通じてdevctlサブシステムにユーザランド通知を送信する処理である。

**業務上の目的・背景**：ディスクデバイスの物理パス、識別子、その他の属性が動的に変更された場合に、ユーザランドがこれを検知する必要がある。例えば、マルチパスストレージ環境でパスの切り替えが発生した場合や、ディスクの識別情報が更新された場合に、devd(8)が適切なアクションを実行するために本通知が必要となる。

**通知の送信タイミング**：ディスクドライバがdisk_attr_changed()を呼び出した際に送信される。属性名は引数として渡され、そのまま通知のtype（第3引数）として使用される。

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

**通知内容の概要**：変更された属性名がtypeとして、ディスクデバイス名が「devname=デバイス名」形式で通知される。

**期待されるアクション**：受信したデーモンは、属性の種類に応じてデバイスエイリアスの更新、物理パスの再設定、デバイス識別情報の更新などを実行する。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

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

## 通知テンプレート

### devctl通知メッセージ

| 項目 | 内容 |
|-----|------|
| system | `GEOM` |
| subsystem | `disk` |
| type | `<属性名>` (例: "GEOM::physpath", "GEOM::ident"等) |
| data | `devname=<ディスクデバイス名>` |

### 本文テンプレート

```
!system=GEOM subsystem=disk type=<属性名> devname=<ディスクデバイス名>
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| type (属性名) | 変更された属性の名前 | disk_attr_changed()の第2引数attr | Yes |
| devname | ディスクデバイス名 | dp->d_name と dp->d_unit から "devname=%s%d" 形式 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| カーネル内部イベント | disk_attr_changed()呼出 | dp->d_geom != NULL（GEOMジオメトリが存在する場合） | ディスクドライバが属性変更を通知 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| gp == NULL | GEOMジオメトリがまだ作成されていない場合は通知が発行されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ディスクドライバが属性変更を検知] --> B[disk_attr_changed呼出]
    B --> C{gp == NULL ?}
    C -->|Yes| D[return 通知なし]
    C -->|No| E[プロバイダにg_attr_changed通知]
    E --> F[snprintf devnamebuf devname=name+unit]
    F --> G[devctl_notify GEOM disk attr devnamebuf]
    G --> H[終了]
```

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

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

| データ構造 | 用途 | 備考 |
|-----------|------|------|
| struct disk | ディスクデバイス情報 | d_name, d_unit, d_geomフィールドを使用 |
| struct g_geom | GEOMジオメトリ | gp->providerリストを参照 |
| struct g_provider | GEOMプロバイダ | g_attr_changed()でプロバイダに属性変更を伝播 |

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

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

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし

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

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

## 備考

- disk_attr_changed()はGEOMプロバイダへのg_attr_changed()呼出とdevctl_notify()の両方を行う
- g_attr_changed()はGEOMの上位クラス（DEVクラス等）にも属性変更を伝播させる。例えば"GEOM::physpath"属性の場合、DEVクラスのg_dev_attrchanged()→g_dev_set_physpath()も呼ばれる
- devnamebufのサイズは128バイト固定で、"devname=%s%d"形式でフォーマットされる
- subsystemが"DEV"ではなく"disk"である点に注意。これはGEOM diskクラス固有の通知であり、DEVクラスの通知とは別系統

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | geom_disk.h | `sys/geom/geom_disk.h` | struct diskの定義：d_name, d_unit, d_geomフィールド |
| 1-2 | geom_disk.c | `sys/geom/geom_disk.c` | g_disk_softc構造体（行64-73） |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | geom_disk.c | `sys/geom/geom_disk.c` | disk_attr_changed()関数（行1006-1019）：通知発行処理 |

**主要処理フロー**:
1. **行1008**: gp = dp->d_geomでGEOMジオメトリを取得
2. **行1012-1013**: gp == NULLの場合はreturn
3. **行1014-1015**: LIST_FOREACHでプロバイダに対してg_attr_changed()を呼出
4. **行1016-1017**: snprintf(devnamebuf, sizeof(devnamebuf), "devname=%s%d", dp->d_name, dp->d_unit)
5. **行1018**: devctl_notify("GEOM", "disk", attr, devnamebuf)

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

```
[ディスクドライバ]
    |
    +-- disk_attr_changed(dp, attr, flag) [sys/geom/geom_disk.c:1006]
            |
            +-- g_attr_changed(pp, attr, flag) [GEOMフレームワーク]
            |       |
            |       +-- g_dev_attrchanged(cp, attr) [sys/geom/geom_dev.c:303]
            |               |
            |               +-- g_dev_set_physpath() [attr=="GEOM::physpath"の場合]
            |               +-- g_dev_set_media() [attr=="GEOM::media"の場合]
            |
            +-- devctl_notify("GEOM", "disk", attr, devnamebuf) [行1018]
```

### データフロー図

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

ディスク属性変更          --->  disk_attr_changed()          --->  g_attr_changed() (GEOM伝播)
(attr, dp)                      |                                   |
                                v                                   v
                          snprintf("devname=%s%d",...)       devctl_notify("GEOM","disk",attr,...)
                                                                    |
                                                                    v
                                                              /dev/devctl
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| geom_disk.c | `sys/geom/geom_disk.c` | ソース | disk_attr_changed()でdisk属性変更通知を発行 |
| geom_disk.h | `sys/geom/geom_disk.h` | ヘッダ | struct diskの定義 |
| geom_dev.c | `sys/geom/geom_dev.c` | ソース | g_dev_attrchanged()で属性変更を受信 |
| devctl.h | `sys/sys/devctl.h` | ヘッダ | devctl_notify()のプロトタイプ |
| subr_bus.c | `sys/kern/subr_bus.c` | ソース | devctl_notify()の実装 |
