# 機能設計書 11-UFS/FFS

## 概要

本ドキュメントは、FreeBSDの標準ディスクファイルシステムであるUFS（Unix File System）/ FFS（Fast File System）の機能設計を記載する。UFS/FFSはFreeBSDのデフォルトファイルシステムとして、ディスク上のファイル・ディレクトリの格納、管理、検索、アクセス制御を提供する。

### 本機能の処理概要

**業務上の目的・背景**：UFS/FFSはFreeBSDの根幹をなすディスクファイルシステムであり、オペレーティングシステムが永続的なデータ保存を行うための基盤機能を提供する。シリンダグループベースのブロック割り当て、inode管理、ジャーナリング（ソフトアップデート）によるデータ整合性の保証が主要な課題解決ポイントである。

**機能の利用シーン**：システムディスクのルートファイルシステムとして利用されるほか、データパーティションのフォーマット・マウント、ファイルシステムの整合性チェック（fsck）、バックアップ・リストア（dump/restore）など、ディスク管理のあらゆる場面で利用される。bsdinstallのパーティション設定画面においてUFS選択時にも本機能が呼び出される。

**主要な処理内容**：
1. ファイルシステムの作成（newfs）：スーパーブロック、シリンダグループ、inodeテーブルの初期化
2. ファイルシステムのマウント・アンマウント（VFS操作）
3. ファイル・ディレクトリの作成、読み取り、更新、削除（vnode操作）
4. ブロック割り当て・解放（ffs_alloc / ffs_blkfree）
5. inode割り当て・解放（ffs_valloc / ffs_vfree）
6. ソフトアップデートによるメタデータ一貫性保証
7. スナップショット機能
8. ファイルシステム整合性チェック（fsck_ffs）
9. ファイルシステムバックアップ・リストア（dump/restore）
10. ディスククォータ、拡張属性、ACLのサポート

**関連システム・外部連携**：GEOMストレージフレームワーク経由でディスクデバイスにアクセスする。VFS（Virtual File System）層を介してカーネルのファイルアクセスAPIと接続される。

**権限による制御**：ファイルシステムのマウント・アンマウントにはroot権限が必要。ファイル・ディレクトリへのアクセスはUNIXパーミッション（owner/group/other）およびオプションでACLにより制御される。ディスククォータによりユーザ・グループ単位でのディスク使用量制限が可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 15 | パーティションモード選択画面 | 遷移先機能 | UFS選択時のautopart処理への遷移 |
| 17 | 手動パーティション編集画面 | 補助機能 | UFSパーティションの作成・マウントポイント設定 |

## 機能種別

CRUD操作 / ストレージ管理 / データ整合性保証

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| デバイスパス | char* | Yes | ファイルシステムを作成/マウントするブロックデバイス | デバイスファイルの存在確認 |
| マウントポイント | char* | Yes | マウント先ディレクトリパス | ディレクトリの存在確認 |
| マウントフラグ | int | No | MNT_RDONLY, MNT_ASYNC, MNT_SOFTDEP等 | 有効なフラグの組み合わせ |
| ブロックサイズ | int | No | newfs時のブロックサイズ（デフォルト32768） | 4096, 8192, 16384, 32768, 65536のいずれか |
| フラグメントサイズ | int | No | newfs時のフラグメントサイズ（デフォルト4096） | ブロックサイズの1/1〜1/8 |

### 入力データソース

- ブロックデバイス（GEOMプロバイダ経由）
- mount(8) / newfs(8) コマンドからのユーザ入力
- /etc/fstab設定ファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ファイルデータ | バイトストリーム | 読み取り要求に対するファイル内容 |
| ファイルメタデータ | struct stat | inode情報（パーミッション、サイズ、タイムスタンプ等） |
| ディレクトリエントリ | struct dirent | ディレクトリ内のファイル一覧 |
| statfs情報 | struct statfs | ファイルシステム容量・使用量情報 |

### 出力先

- VFS層を介したユーザ空間アプリケーション
- カーネル内バッファキャッシュ

## 処理フロー

### 処理シーケンス

```
1. ファイルシステム作成（newfs）
   └─ スーパーブロック初期化 → シリンダグループ初期化 → ルートディレクトリinode作成
2. マウント処理（ffs_mount / ffs_mountfs）
   └─ スーパーブロック読み込み → 検証 → ufsmount構造体初期化 → シリンダグループサマリ読み込み
3. ファイル操作（ufs_vnops / ffs_vnops）
   └─ VFS経由でvnode操作関数が呼ばれ、inodeとブロックを操作
4. ブロック割り当て（ffs_alloc）
   └─ シリンダグループ内の空きブロック検索 → ビットマップ更新 → ブロック返却
5. ソフトアップデート（ffs_softdep）
   └─ メタデータ更新の依存関係を追跡し、安全な書き込み順序を保証
6. アンマウント処理（ffs_unmount）
   └─ ダーティバッファのフラッシュ → スーパーブロック更新 → リソース解放
```

### フローチャート

```mermaid
flowchart TD
    A[mount要求] --> B[ffs_mount]
    B --> C{新規マウント?}
    C -->|Yes| D[ffs_mountfs]
    C -->|No| E[フラグ更新]
    D --> F[スーパーブロック読み込み]
    F --> G[スーパーブロック検証]
    G --> H{有効?}
    H -->|Yes| I[ufsmount初期化]
    H -->|No| J[エラー返却]
    I --> K[シリンダグループサマリ読み込み]
    K --> L[マウント完了]
    E --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-11-01 | UFS1/UFS2判別 | スーパーブロックのマジックナンバーにより UFS1(FS_UFS1_MAGIC) / UFS2(FS_UFS2_MAGIC) を判別 | マウント時 |
| BR-11-02 | スーパーブロック位置検索 | SBLOCK_UFS2(64K), SBLOCK_UFS1(8K), SBLOCK_FLOPPY(0), SBLOCK_PIGGY(256K) の順に検索 | マウント時 |
| BR-11-03 | ソフトアップデート依存順序 | メタデータの書き込みは依存関係グラフに従い、親ディレクトリ更新→inode更新→ブロック割り当ての順序を保証 | 書き込み時 |
| BR-11-04 | フラグメント割り当て | ブロックサイズより小さいファイルにはフラグメント単位で割り当て | ファイル書き込み時 |

### 計算ロジック

- シリンダグループ開始位置: `cgbase(fs, cg)` マクロにより計算
- 空きブロック数: シリンダグループごとのビットマップから集計
- inode番号: シリンダグループ番号 * グループあたりinode数 + グループ内オフセット

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ファイル作成 | inodeテーブル / データブロック | INSERT | 新規inode割り当てとデータブロック書き込み |
| ファイル読み取り | inodeテーブル / データブロック | SELECT | inodeからブロックマップ参照、データブロック読み取り |
| ファイル更新 | データブロック / inodeテーブル | UPDATE | データブロック上書きとinode更新（サイズ、タイムスタンプ） |
| ファイル削除 | inodeテーブル / ディレクトリエントリ | DELETE | inode解放とディレクトリエントリ削除 |

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

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

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | fs_fmod | マウント後の変更フラグ | sync時にクリア |
| SELECT | fs_magic | FS_UFS1_MAGIC / FS_UFS2_MAGIC | マウント時の判別 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EINVAL | バリデーション | 不正なスーパーブロック（マジックナンバー不一致） | fsck_ffsで修復 |
| ENOSPC | リソース不足 | 空きブロック/inode不足 | 不要ファイル削除またはファイルシステム拡張 |
| EIO | I/Oエラー | ディスク読み書き失敗 | ディスク状態確認 |
| EROFS | 権限エラー | 読み取り専用ファイルシステムへの書き込み | マウントオプション変更 |
| EDQUOT | クォータ超過 | ディスククォータ制限超過 | クォータ設定見直し |

### リトライ仕様

ディスクI/Oエラー時はGEOM層およびCAMサブシステムでリトライが行われる。ファイルシステム層では通常リトライを行わず、エラーを上位に返す。

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

ソフトアップデート（Soft Updates）によりメタデータの更新順序を保証する。ジャーナリング付きソフトアップデート（SUJ: Soft Updates with Journaling）を有効にすることで、クラッシュ後の高速なfsckが可能となる。トランザクションログはジャーナル領域に書き込まれる。

## パフォーマンス要件

- シリンダグループ単位でのローカリティ最適化によりシーケンシャルアクセス性能を向上
- ディレクトリハッシュ（UFS_DIRHASH）による大規模ディレクトリの検索高速化
- 非同期書き込み（MNT_ASYNC）オプションによるスループット向上（データ消失リスクあり）
- ブロック先読み（read-ahead）によるシーケンシャル読み取り性能の最適化

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

- UNIXパーミッション（owner/group/other）によるアクセス制御
- POSIX.1e ACLによる細粒度アクセス制御（オプション）
- 拡張属性（extattr）によるセキュリティラベルの付与（MACフレームワーク連携）
- setuid/setgidビットの制御（nosuidマウントオプション）
- ファイルフラグ（schg, sunlnk等）による保護

## 備考

- UFS1は32ビットブロックアドレッシング、UFS2は64ビットブロックアドレッシングに対応
- FreeBSD現在のデフォルトはUFS2
- ソフトアップデートジャーナリング（SUJ）はデフォルトで有効
- スナップショット機能によりオンラインfsckやバックアップが可能

---

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

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

### 推奨読解順序

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

まず、UFS/FFSのオンディスク構造とインメモリ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | fs.h | `sys/ufs/ffs/fs.h` | スーパーブロック構造体（struct fs, 340行目）、シリンダグループ構造、マジックナンバー定義 |
| 1-2 | dinode.h | `sys/ufs/ufs/dinode.h` | ディスク上のinode構造体（UFS1/UFS2ディスクinode） |
| 1-3 | inode.h | `sys/ufs/ufs/inode.h` | インメモリinode構造体（struct inode, 79行目）、VTOI/ITOVマクロ（262行目） |
| 1-4 | dir.h | `sys/ufs/ufs/dir.h` | ディレクトリエントリ構造体 |
| 1-5 | ufsmount.h | `sys/ufs/ufs/ufsmount.h` | マウント情報構造体（struct ufsmount） |

**読解のコツ**: UFS/FFSではオンディスク構造（dinode.h, fs.h）とインメモリ構造（inode.h）が明確に分離されている。VTOI()マクロでvnodeからinodeを取得し、I_IS_UFS1()/I_IS_UFS2()（216行目、223行目）でUFS1/UFS2を判別する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ffs_vfsops.c | `sys/ufs/ffs/ffs_vfsops.c` | VFS操作の実装。マウント、アンマウント、sync等 |

**主要処理フロー**:
1. **101-118行目**: ufs_vfsops構造体の定義とVFS_SETによるファイルシステム登録
2. **347行目**: ffs_mount() - マウント処理のエントリーポイント
3. **869行目**: ffs_mountfs() - 実際のマウント処理（スーパーブロック読み込み、検証）
4. **1226行目**: ffs_unmount() - アンマウント処理
5. **1425行目**: ffs_statfs() - ファイルシステム統計情報取得
6. **1540行目**: ffs_sync() - ファイルシステム同期

#### Step 3: vnode操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ufs_vnops.c | `sys/ufs/ufs/ufs_vnops.c` | UFS共通のvnode操作（create, remove, rename, readdir等） |
| 3-2 | ffs_vnops.c | `sys/ufs/ffs/ffs_vnops.c` | FFS固有のvnode操作（read, write等） |

#### Step 4: ブロック割り当てを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ffs_alloc.c | `sys/ufs/ffs/ffs_alloc.c` | ブロック・inode割り当て/解放の中核ロジック |

**主要処理フロー**:
- **150行目**: ffs_alloc() - ブロック割り当て
- **251行目**: ffs_realloccg() - ブロック再割り当て（フラグメント拡張）
- **1111行目**: ffs_valloc() - inode割り当て
- **2671行目**: ffs_blkfree() - ブロック解放
- **2820行目**: ffs_vfree() - inode解放

#### Step 5: ソフトアップデートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | ffs_softdep.c | `sys/ufs/ffs/ffs_softdep.c` | メタデータ一貫性保証のソフトアップデート機構 |
| 5-2 | softdep.h | `sys/ufs/ffs/softdep.h` | ソフトアップデート用データ構造定義 |

#### Step 6: ユーザ空間ツールを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | newfs.c | `sbin/newfs/newfs.c` | newfsコマンドのmain関数（118行目） |
| 6-2 | mkfs.c | `sbin/newfs/mkfs.c` | ファイルシステム作成の実装 |
| 6-3 | main.c | `sbin/fsck_ffs/main.c` | fsck_ffsのmain関数（67行目）。5パス構成の整合性チェック |
| 6-4 | main.c | `sbin/dump/main.c` | dumpコマンド（バックアップ） |
| 6-5 | main.c | `sbin/restore/main.c` | restoreコマンド（リストア） |

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

```
VFS層（sys/kern/vfs_*）
    │
    ├─ ffs_vfsops.c（VFS操作）
    │      ├─ ffs_mount() → ffs_mountfs()
    │      ├─ ffs_unmount()
    │      ├─ ffs_sync()
    │      └─ ffs_statfs()
    │
    ├─ ufs_vnops.c（UFS共通vnode操作）
    │      ├─ ufs_create() / ufs_remove()
    │      ├─ ufs_rename()
    │      ├─ ufs_readdir()
    │      └─ ufs_lookup.c → ufs_lookup()
    │
    ├─ ffs_vnops.c（FFS固有vnode操作）
    │      ├─ ffs_read() / ffs_write()
    │      └─ ffs_truncate()
    │
    ├─ ffs_alloc.c（ブロック/inode管理）
    │      ├─ ffs_alloc() / ffs_blkfree()
    │      └─ ffs_valloc() / ffs_vfree()
    │
    ├─ ffs_balloc.c（ブロック割り当て制御）
    │
    ├─ ffs_softdep.c（ソフトアップデート）
    │
    └─ ffs_snapshot.c（スナップショット）

ユーザ空間ツール:
    newfs(8) → mkfs.c → ディスク上にFS構造作成
    fsck_ffs(8) → pass1〜pass5 → 整合性チェック・修復
    dump(8) / restore(8) → バックアップ/リストア
```

### データフロー図

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

ブロックデバイス ──────▶ ffs_mountfs()              ──▶ マウント済みFS
                         （スーパーブロック読み込み）

ユーザI/O要求    ──────▶ ffs_read()/ffs_write()     ──▶ ファイルデータ
                         ↓
                         ffs_alloc()/ffs_blkfree()
                         （ブロック管理）
                         ↓
                         ffs_softdep
                         （メタデータ一貫性保証）
                         ↓
                         GEOM層 → ディスクI/O
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| fs.h | `sys/ufs/ffs/fs.h` | ヘッダ | スーパーブロック構造体・定数定義 |
| dinode.h | `sys/ufs/ufs/dinode.h` | ヘッダ | ディスクinode構造体 |
| inode.h | `sys/ufs/ufs/inode.h` | ヘッダ | インメモリinode構造体 |
| dir.h | `sys/ufs/ufs/dir.h` | ヘッダ | ディレクトリエントリ構造体 |
| ufsmount.h | `sys/ufs/ufs/ufsmount.h` | ヘッダ | マウント情報構造体 |
| ffs_vfsops.c | `sys/ufs/ffs/ffs_vfsops.c` | ソース | VFS操作実装 |
| ffs_vnops.c | `sys/ufs/ffs/ffs_vnops.c` | ソース | FFS vnode操作 |
| ffs_alloc.c | `sys/ufs/ffs/ffs_alloc.c` | ソース | ブロック/inode割り当て |
| ffs_balloc.c | `sys/ufs/ffs/ffs_balloc.c` | ソース | ブロック割り当て制御 |
| ffs_inode.c | `sys/ufs/ffs/ffs_inode.c` | ソース | inode操作 |
| ffs_softdep.c | `sys/ufs/ffs/ffs_softdep.c` | ソース | ソフトアップデート |
| ffs_snapshot.c | `sys/ufs/ffs/ffs_snapshot.c` | ソース | スナップショット機能 |
| ffs_rawread.c | `sys/ufs/ffs/ffs_rawread.c` | ソース | 生データ読み取り |
| ffs_suspend.c | `sys/ufs/ffs/ffs_suspend.c` | ソース | ファイルシステム一時停止 |
| ufs_vnops.c | `sys/ufs/ufs/ufs_vnops.c` | ソース | UFS共通vnode操作 |
| ufs_lookup.c | `sys/ufs/ufs/ufs_lookup.c` | ソース | ディレクトリ検索 |
| ufs_quota.c | `sys/ufs/ufs/ufs_quota.c` | ソース | ディスククォータ |
| ufs_acl.c | `sys/ufs/ufs/ufs_acl.c` | ソース | ACLサポート |
| ufs_extattr.c | `sys/ufs/ufs/ufs_extattr.c` | ソース | 拡張属性 |
| ufs_dirhash.c | `sys/ufs/ufs/ufs_dirhash.c` | ソース | ディレクトリハッシュ |
| newfs.c | `sbin/newfs/newfs.c` | ソース | newfsコマンド |
| mkfs.c | `sbin/newfs/mkfs.c` | ソース | FS作成ロジック |
| main.c | `sbin/fsck_ffs/main.c` | ソース | fsckメイン |
| main.c | `sbin/dump/main.c` | ソース | dumpコマンド |
| main.c | `sbin/restore/main.c` | ソース | restoreコマンド |
