# 帳票設計書 37-dumpfs

## 概要

本ドキュメントは、FreeBSDのdumpfsコマンドが生成するUFSファイルシステム情報レポートの設計を記述する。dumpfsはUFS（Unix File System）のスーパーブロック、シリンダーグループ、空きブロック情報などのメタデータを詳細にダンプするCLIユーティリティである。

### 本帳票の処理概要

dumpfsコマンドは、libufs(3)ライブラリを使用してUFS/UFS2ファイルシステムのスーパーブロックおよびシリンダーグループ情報を読み取り、ファイルシステムの内部構造を人間が読める形式で出力する。オプションにより、空きブロック一覧やnewfsコマンド再現用パラメータの出力も可能である。

**業務上の目的・背景**：ファイルシステムの内部構造を確認することは、fsck(8)の前後比較、ファイルシステム障害の診断、ファイルシステムのパフォーマンスチューニング、データリカバリなどに不可欠である。

**帳票の利用シーン**：fsck前後のファイルシステム状態比較、ファイルシステム障害時のメタデータ調査、ファイルシステムの空き領域分析、newfsパラメータの復元、シリンダーグループの健全性確認に利用される。

**主要な出力内容**：
1. スーパーブロック情報（magic/サイズ/ブロック数/inode数/フラグ等）
2. シリンダーグループサマリー（空きブロック/ディレクトリ/inode数）
3. 各シリンダーグループの詳細（rotor/使用中inode/空きブロックビットマップ）
4. 空きブロック一覧（-fオプション）
5. newfsコマンド復元（-mオプション）
6. ファイルシステムID（-lオプション）

**帳票の出力タイミング**：ユーザーがdumpfsコマンドを実行した際に即時出力される。

**帳票の利用者**：システム管理者、ファイルシステムエンジニア

## 帳票種別

詳細ダンプレポート

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | CLIターミナル | N/A | `dumpfs [-flms] filesys | device` コマンド実行 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（標準出力） |
| 用紙サイズ | N/A（ターミナル出力） |
| 向き | N/A |
| ファイル名 | N/A（標準出力） |
| 出力方法 | 標準出力（stdout） |
| 文字コード | ASCII |

### PDF固有設定

該当なし

### Excel固有設定

該当なし

## 帳票レイアウト

### レイアウト概要

```
┌──────────────────────────────────────────────────────────────────┐
│  スーパーブロック情報（タブ区切りkey-value形式）                      │
│  magic  0x19540119 (UFS2)                                        │
│  ncg    N    size    N    blocks    N                             │
│  bsize  N    shift   N    mask    0xXXXXXXXX                     │
│  ...                                                             │
├──────────────────────────────────────────────────────────────────┤
│  cs[].cs_(nbfree,ndir,nifree,nffree):                            │
│    (N,N,N,N) (N,N,N,N) ...                                       │
├──────────────────────────────────────────────────────────────────┤
│  cg N:                                                           │
│  magic  0xXXXX  tell  0xXXXX  time  ...                          │
│  nbfree  N  ndir  N  nifree  N  nffree  N                        │
│  rotor  N  irotor  N  frotor  N                                  │
│  frsum  N  N  N  ...                                              │
│  inodes used: N-N, N-N, ...                                      │
│  blks free: N-N, N-N, ...                                        │
│  ...                                                             │
└──────────────────────────────────────────────────────────────────┘
```

### ヘッダー部

該当なし（スーパーブロック情報が先頭に出力される）

### 明細部

#### スーパーブロック情報（dumpfs関数 行147-330）

**UFS2固有フィールド（行156-167）**

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | magic | マジックナンバー | fs_magic | "%x (UFS2)" |
| 2 | last mounted time | 最終マウント時刻 | fs_mtime | ctime() |
| 3 | last modified time | 最終変更時刻 | fs_time | ctime() |
| 4 | superblock location | スーパーブロック位置 | fs_sblockloc | "%jd" |
| 5 | id | ファイルシステムID | fs_id[0], fs_id[1] | "%08x %08x" |
| 6 | ncg | シリンダーグループ数 | fs_ncg | "%d" |
| 7 | size | ファイルシステムサイズ | fs_size | "%jd" |
| 8 | blocks | データブロック数 | fs_dsize | "%jd" |

**共通フィールド（行181-301）**

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | bsize/shift/mask | ブロックサイズ関連 | fs_bsize, fs_bshift, fs_bmask | "%d / %d / 0x%08x" |
| 2 | fsize/shift/mask | フラグメントサイズ関連 | fs_fsize, fs_fshift, fs_fmask | "%d / %d / 0x%08x" |
| 3 | frag/shift/fsbtodb | フラグメント関連 | fs_frag, fs_fragshift, fs_fsbtodb | "%d / %d / %d" |
| 4 | minfree | 最小空き割合 | fs_minfree | "%d%%" |
| 5 | optim | 最適化方針 | fs_optim | "space" or "time" |
| 6 | nbfree/ndir/nifree/nffree | 空きリソースサマリー | fs_cstotal | "%jd" |
| 7 | bpg/fpg/ipg | グループ当たりのリソース | fs_fpg/fs_frag, fs_fpg, fs_ipg | "%d" |
| 8 | flags | ファイルシステムフラグ | fs_flags | テキスト文字列 |
| 9 | fsmnt | マウントポイント | fs_fsmnt | "%s" |
| 10 | volname | ボリューム名 | fs_volname | "%s" |

**フラグ文字列（行246-276）**

| フラグ定数 | 表示文字列 |
|-----------|----------|
| FS_UNCLEAN | "unclean" |
| FS_DOSOFTDEP | "soft-updates" |
| FS_SUJ | "+journal" |
| FS_NEEDSFSCK | "needs-fsck-run" |
| FS_INDEXDIRS | "indexed-directories" |
| FS_ACLS | "acls" |
| FS_MULTILABEL | "multilabel" |
| FS_GJOURNAL | "gjournal" |
| FS_NFS4ACLS | "nfsv4acls" |
| FS_TRIM | "trim" |

#### シリンダーグループ詳細（dumpcg関数 行332-390）

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | cg番号 | シリンダーグループ番号 | disk.d_lcg | "cg %d:" |
| 2 | magic | CGマジック | acg.cg_magic | "%x" |
| 3 | tell | ディスク位置 | fsbtodb計算 | "%jx" |
| 4 | time | タイムスタンプ | cg_time / cg_old_time | ctime() |
| 5 | cgx/ndblk/niblk | CG内リソース | acg.cg_cgx等 | "%d" |
| 6 | nbfree/ndir/nifree/nffree | CG空きリソース | acg.cg_cs | "%d" |
| 7 | rotor/irotor/frotor | アロケーションローター | acg.cg_rotor等 | "%d" |
| 8 | frsum | フラグメントサマリー | acg.cg_frsum[] | "%d" |
| 9 | clusters | クラスターサマリー | cg_clustersum | "%d" |
| 10 | inodes used | 使用中inodeビットマップ | cg_inosused | "N-N" |
| 11 | blks free | 空きブロックビットマップ | cg_blksfree | "N-N" |

#### newfs復元出力（marshal関数 行421-474）

| No | 項目名 | 説明 | newfsオプション |
|----|-------|------|---------------|
| 1 | volume name | ボリューム名 | -L |
| 2 | UFS version | UFSバージョン | -O |
| 3 | soft-updates | ソフトアップデート有効 | -U |
| 4 | maxcontig | 最大連続ブロック | -a |
| 5 | bsize | ブロックサイズ | -b |
| 6 | maxbsize | 最大ブロックサイズ | -d |
| 7 | maxbpg | グループ当たり最大ブロック | -e |
| 8 | fsize | フラグメントサイズ | -f |
| 9 | avgfilesize | 平均ファイルサイズ | -g |
| 10 | avgfpdir | ディレクトリ当たり平均ファイル数 | -h |
| 11 | minfree | 最小空き割合 | -m |
| 12 | optim | 最適化方針 | -o |
| 13 | size | ファイルシステムサイズ | -s |

### フッター部

該当なし

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| デバイス/ファイルシステム | 対象デバイスまたはファイルシステム | Yes |
| -f | 空きブロック一覧出力（-ffで個別ブロック表示） | No |
| -m | newfsコマンド復元出力 | No |
| -l | ファイルシステムIDのみ出力 | No |
| -s | スーパーブロックのみ出力（CGスキップ） | No |

### ソート順

シリンダーグループ番号順（0から順に出力）

### 改ページ条件

改ページなし

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| UFS スーパーブロック | ファイルシステムメタデータ | sbfind()による自動検出 |
| シリンダーグループ | CG情報 | cgread()による読取 |

### テーブル別参照項目詳細

#### struct fs（スーパーブロック）

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| fs_magic | magic | sbfind() | UFS1: 0x011954, UFS2: 0x19540119 |
| fs_size | size | sbfind() | フラグメント数 |
| fs_ncg | ncg | sbfind() | シリンダーグループ数 |
| fs_bsize | bsize | sbfind() | ブロックサイズ（バイト） |
| fs_fsize | fsize | sbfind() | フラグメントサイズ |
| fs_cstotal | 空きリソースサマリー | sbfind() | csum構造体 |
| fs_flags | flags | sbfind() | ファイルシステムフラグ |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| bpg（ブロック/グループ） | fs_fpg / fs_frag | N/A | 行200 |
| CG位置 | fsbtodb(cgtod(fs, lcg)) * disk.d_bsize | N/A | 行340 |
| frsum合計 | SUM(cg_frsum[1..fs_frag-1] * i) | N/A | 行366-369 |
| inodeバイト数 | fragroundup(fs, lblktosize(fs, fragstoblks(fs, fs_fpg)) / fs_ipg) | N/A | marshal行443 |
| last group blocks | (fssize % fs_fpg) / fs_frag | N/A | 行317 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[コマンド実行] --> B[getoptによるオプション解析]
    B --> C[ufs_disk_fillout_blank + sbfind]
    C --> D{オプション判定}
    D -->|-f| E[dumpfreespace: 空きブロック一覧]
    D -->|-m| F[marshal: newfsコマンド復元]
    D -->|-l| G[dumpfsid: ファイルシステムID]
    D -->|デフォルト| H[dumpfs: フルダンプ]
    H --> I[スーパーブロック情報出力]
    I --> J[cs配列出力]
    J --> K{-s?}
    K -->|Yes| L[終了]
    K -->|No| M[cgreadループ]
    M --> N[dumpcg: CG詳細出力]
    N --> M
    E --> O[cgreadループ]
    O --> P[dumpfreespacecg: CG空きブロック]
    P --> O
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| スーパーブロック不在 | sbfind失敗 | ufserr()メッセージ | デバイス名確認 |
| CG読取失敗 | cgread失敗 | "cg N: disk.d_error" | ファイルシステム修復 |
| オプション競合 | -fと-mを同時指定 | usage表示 | いずれか1つを選択 |
| -f 3回以上 | -fを3回以上指定 | usage表示 | -fは最大2回 |
| 引数不足 | デバイス未指定 | usage表示 | デバイス指定 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1ファイルシステム（CG数に依存） |
| 目標出力時間 | 数秒（ディスクI/Oに依存） |
| 同時出力数上限 | 制限なし |

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

- デバイスへの直接アクセスにはroot権限またはoperatorグループが通常必要
- ファイルシステムのメタデータ構造が公開されるため、ディスクレイアウト情報の漏洩に注意

## 備考

- UFS1とUFS2の両方に対応（disk.d_ufsで判別）
- libufs(3)ライブラリ（ufs_disk_fillout_blank, sbfind, cgread）を使用
- -fオプションの指定回数で動作が変わる（1回: 範囲表示、2回: 個別ブロック表示）
- csサマリーは4件ずつ改行して出力（行305-306）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | dumpfs.c | `sbin/dumpfs/dumpfs.c` | 行66-68: afs/acg マクロ（disk.d_fs, disk.d_cg へのエイリアス） |
| 1-2 | dumpfs.c | `sbin/dumpfs/dumpfs.c` | 行69: static struct uufsd disk（libufsディスクハンドル） |

**読解のコツ**: afs は disk.d_fs (struct fs) へのマクロ、acg は disk.d_cg (struct cg) へのマクロ。直接的にスーパーブロックとシリンダーグループにアクセスする。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dumpfs.c | `sbin/dumpfs/dumpfs.c` | 行82-137: main関数 |

**主要処理フロー**:
1. **行90-107**: getoptによるオプション解析（f/l/m/s）
2. **行114-115**: 排他チェック（-fと-m）、-fの回数チェック
3. **行119-121**: ufs_disk_fillout_blank + sbfindでスーパーブロック読取
4. **行126-134**: オプションに応じた出力関数呼び出し

#### Step 3: スーパーブロックダンプ（dumpfs）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dumpfs.c | `sbin/dumpfs/dumpfs.c` | 行147-330: dumpfs関数 |

**主要処理フロー**:
- **行155-180**: UFS2/UFS1判定とバージョン固有情報出力
- **行181-296**: 共通フィールド出力（bsize/fsize/frag/minfree/flags等）
- **行302-310**: csサマリー配列出力
- **行322-329**: cgreadループによるCGダンプ

#### Step 4: シリンダーグループダンプ（dumpcg）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | dumpfs.c | `sbin/dumpfs/dumpfs.c` | 行332-390: dumpcg関数 |

**主要処理フロー**:
- **行341-360**: UFS2/UFS1固有のCGヘッダー出力
- **行361-365**: 空きリソースサマリー出力
- **行366-389**: frsum/clusters/inodes used/blks freeのビットマップ出力

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

```
main() [dumpfs.c:82]
    |
    +-- getopt() [オプション解析]
    +-- ufs_disk_fillout_blank() [libufs]
    +-- sbfind() [libufs: スーパーブロック検出]
    |
    +-- dumpfs() [dumpfs.c:147]
    |       +-- printf() [スーパーブロック情報出力]
    |       +-- cgread() [libufs: CG読取]
    |       +-- dumpcg() [dumpfs.c:332]
    |              +-- pbits() [ビットマップ出力]
    |
    +-- dumpfreespace() [dumpfs.c:392]
    |       +-- cgread() [libufs]
    |       +-- dumpfreespacecg() [dumpfs.c:413]
    |              +-- pblklist() [空きブロック一覧出力]
    |
    +-- marshal() [dumpfs.c:421]
    |       +-- printf() [newfsコマンド出力]
    |
    +-- dumpfsid() [dumpfs.c:139]
            +-- printf() [FS ID出力]
```

### データフロー図

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

デバイス/FS名 ──────> ufs_disk_fillout_blank()       ──> diskハンドル
                           |                                |
ディスク ────────> sbfind() [スーパーブロック読取]     ──> struct fs (afs)
                           |                                |
struct fs ──────> dumpfs() [フォーマット出力]          ──> 標準出力
                           |                                |
ディスク ────────> cgread() [CG読取]                  ──> struct cg (acg)
                           |                                |
struct cg ──────> dumpcg() [フォーマット出力]          ──> 標準出力
                           |                                |
空きブロックBM ──> pbits()/pblklist()                 ──> ビットマップ/一覧
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dumpfs.c | `sbin/dumpfs/dumpfs.c` | ソース | メインプログラム |
| Makefile | `sbin/dumpfs/Makefile` | 設定 | ビルド設定 |
| fs.h | `sys/ufs/ffs/fs.h` | ヘッダ | struct fs, struct cg定義 |
| dinode.h | `sys/ufs/ufs/dinode.h` | ヘッダ | inode構造体定義 |
| libufs.h | `/usr/include/libufs.h` | ヘッダ | libufs API（struct uufsd等） |
