# 機能設計書 75-ディスククォータ

## 概要

本ドキュメントは、FreeBSDのファイルシステムディスク使用量制限機能（ディスククォータ）の設計について記述する。edquota(8)によるクォータの設定・編集、quotacheck(8)によるクォータデータベースの整合性チェック・初期化を中心に、ユーザ・グループごとのディスク使用量制限を管理する。

### 本機能の処理概要

**業務上の目的・背景**：マルチユーザ環境では、特定のユーザやグループによるディスク領域の過剰消費を防止する必要がある。ディスククォータにより、ユーザ・グループごとにブロック数（ディスク容量）およびinode数（ファイル数）の使用上限を設定し、公平なリソース配分を実現する。

**機能の利用シーン**：新規ファイルシステムのクォータ初期設定（quotacheck）、ユーザごとのディスク使用量上限変更（edquota）、グレースタイム（猶予期間）の設定（edquota -t）、クォータ状態の確認。

**主要な処理内容**：
1. edquota(8): ユーザ・グループのクォータ値（ソフトリミット・ハードリミット）をエディタで編集
2. quotacheck(8): ファイルシステムをスキャンしてinode/ブロック使用量を集計し、クォータデータベース（quota.user、quota.group）を更新
3. クォータ値の表示・設定（ブロック数はKB単位、inode数は個数）
4. グレースタイム（ソフトリミット超過後の猶予期間）の管理

**関連システム・外部連携**：UFS/FFSファイルシステムのクォータサポート（sys/ufs/ufs/quota.h）、fstab(5)によるクォータ有効ファイルシステムの指定、エディタ（EDITOR環境変数）による対話的編集。

**権限による制御**：edquotaおよびquotacheckはroot権限が必要。一般ユーザは自身のクォータ状態のみ参照可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （画面なし） | - | コマンドラインツールであり直接的な画面UIを持たない |

## 機能種別

CRUD操作 / リソース管理

## 入力仕様

### 入力パラメータ（edquota）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -u | フラグ | No | ユーザクォータの編集（デフォルト） | なし |
| -g | フラグ | No | グループクォータの編集 | なし |
| -h | フラグ | No | 人間可読形式で表示 | なし |
| -e | 文字列 | No | コマンドラインからクォータ値を直接指定 | fs:blocks:inodes形式 |
| -f | 文字列 | No | 対象ファイルシステムの指定 | マウントポイントまたはデバイス |
| -p | 文字列 | No | プロトタイプユーザからクォータをコピー | 既存ユーザ名 |
| -t | フラグ | No | グレースタイムの編集 | なし |
| user/group | 文字列 | Yes | 対象ユーザ名/グループ名（複数指定可） | 存在するユーザ/グループ |

### 入力パラメータ（quotacheck）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -a | フラグ | No | fstab内の全クォータ有効ファイルシステムを対象 | なし |
| -g | フラグ | No | グループクォータのみチェック | なし |
| -u | フラグ | No | ユーザクォータのみチェック | なし |
| -v | フラグ | No | 詳細出力 | なし |
| -c | 整数 | No | クォータファイル形式の変換（32 or 64ビット） | 32 or 64 |
| filesystem | 文字列 | No | 対象ファイルシステム | -a未指定時は必須 |

### 入力データソース

- コマンドライン引数
- /etc/fstab（クォータ有効ファイルシステムの識別）
- quota.user / quota.group（既存クォータデータベース）
- EDITOR環境変数で指定されたエディタ（edquota使用時）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| quota.user | バイナリファイル | ユーザクォータデータベース |
| quota.group | バイナリファイル | グループクォータデータベース |

### 出力先

- ファイルシステムルートのquota.user / quota.group（クォータデータベースファイル）

## 処理フロー

### 処理シーケンス

```
edquota:
1. 引数解析
   └─ ユーザ/グループ、ファイルシステムの指定
2. 現在のクォータ値取得
   └─ quotactl(2)でクォータ情報を読み出し
3. テンポラリファイル作成
   └─ クォータ値をテキスト形式で書き出し
4. エディタ起動
   └─ EDITOR環境変数のエディタでテンポラリファイルを編集
5. 編集結果の解析
   └─ テンポラリファイルから変更後のクォータ値を読み出し
6. クォータ値の更新
   └─ quotactl(2)で新しいクォータ値を設定

quotacheck:
1. 対象ファイルシステムの決定
   └─ -a指定時はfstabから全クォータ有効FSを取得
2. ファイルシステムのスキャン
   └─ 全inodeをスキャンしてUID/GIDごとの使用量を集計
3. クォータデータベースとの比較
   └─ 既存クォータDBの値と実使用量を比較
4. データベースの更新
   └─ 不整合があればクォータDBを更新
```

### フローチャート

```mermaid
flowchart TD
    A[edquota起動] --> B[引数解析]
    B --> C[対象ユーザ/グループのクォータ取得]
    C --> D{-e指定?}
    D -->|Yes| E[コマンドラインから値設定]
    D -->|No| F[テンポラリファイル作成]
    F --> G[エディタ起動]
    G --> H[編集結果解析]
    H --> I{-p指定?}
    I -->|Yes| J[プロトタイプからコピー]
    I -->|No| K[クォータ値更新]
    E --> K
    J --> K
    K --> L[quotactl で設定]
    L --> M[完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-75-01 | ソフトリミット/ハードリミット | ソフトリミットを超過するとグレースタイム開始、ハードリミット超過は即座に拒否 | クォータ設定時 |
| BR-75-02 | グレースタイム | ソフトリミット超過状態がグレースタイムを超えると、ハードリミットと同等の制限となる | ソフトリミット超過中 |
| BR-75-03 | ブロック単位 | edquotaの表示・設定はKB単位、内部はDEV_BSHIFTに基づく変換 | 表示・入力時 |
| BR-75-04 | クォータファイル配置 | クォータファイルはファイルシステムルートに配置（quota.user, quota.group） | 常時 |

### 計算ロジック

- KB変換: `dbtokb(db) = (off_t)(db) >> (10-DEV_BSHIFT)` （DEV_BSHIFTが10未満の場合のシフト演算）
- edquota.c 62-69行目に定義

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| edquota | quota.user / quota.group | UPDATE | ユーザ/グループのクォータ値（ソフト/ハードリミット）を更新 |
| quotacheck | quota.user / quota.group | UPDATE | ファイルシステムスキャン結果に基づく使用量の更新 |

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

#### quota.user / quota.group（dqblk構造体）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | dqb_bhardlimit | ブロック数ハードリミット | quotactl(2)経由 |
| UPDATE | dqb_bsoftlimit | ブロック数ソフトリミット | quotactl(2)経由 |
| UPDATE | dqb_ihardlimit | inode数ハードリミット | quotactl(2)経由 |
| UPDATE | dqb_isoftlimit | inode数ソフトリミット | quotactl(2)経由 |
| UPDATE | dqb_curblocks | 現在のブロック使用量 | quotacheckで更新 |
| UPDATE | dqb_curinodes | 現在のinode使用量 | quotacheckで更新 |
| UPDATE | dqb_btime | ブロックソフトリミット超過時刻 | 超過検出時に設定 |
| UPDATE | dqb_itime | inodeソフトリミット超過時刻 | 超過検出時に設定 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 権限エラー | root権限なし | エラーメッセージ出力 |
| - | FS未対応 | クォータ非対応ファイルシステム | エラーメッセージ出力 |
| - | ユーザ不在 | 指定ユーザが存在しない | エラーメッセージ出力 |
| - | エディタエラー | エディタ終了コード異常 | エラーメッセージ出力 |
| - | フォーマットエラー | 編集後のクォータ値が不正 | エラーメッセージ出力、再編集促す |

### リトライ仕様

edquotaではエディタによる編集後に値のパースエラーが発生した場合、再度エディタを起動して修正を促す。

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

quotacheckはファイルシステムをスキャンしてクォータDBを一括更新する。スキャン中のファイルシステム変更は反映されないため、シングルユーザモードでの実行が推奨される。

## パフォーマンス要件

quotacheckのファイルシステムスキャンは全inodeを走査するため、大容量ファイルシステムでは相応の時間を要する。

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

- クォータ操作はroot権限のみ可能
- edquotaのテンポラリファイルは/tmp以下に安全に作成される（tmpfil変数）
- クォータによるリソース制限はDoS攻撃の緩和に寄与

## 備考

- ディスククォータはUFS/FFSファイルシステムでのみサポートされる。ZFSには独自のクォータ機構がある。
- quotacheck -cオプションによりクォータファイル形式の32ビット/64ビット変換が可能。
- hflagにより人間可読形式（K/M/G等）での表示が可能。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | quota.h | `sys/ufs/ufs/quota.h` | dqblk構造体（クォータ値保持）、QUOTAFILENAMEマクロ、INITQFNAMES定義を理解する |
| 1-2 | edquota.c | `usr.sbin/edquota/edquota.c` | quotause構造体（クォータ操作用リンクドリスト）、dbtokbマクロ（ブロック-KB変換）を理解する |

**読解のコツ**: dqblk構造体はUFSクォータの核心データ構造。bhardlimit/bsoftlimit（ブロック制限）とihardlimit/isoftlimit（inode制限）のペアで管理される。DEV_BSHIFTによるブロックサイズ変換に注意。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | edquota.c | `usr.sbin/edquota/edquota.c` | main関数のオプション解析、getprivs/putprivs関数（クォータ値の取得・設定）、editit関数（エディタ起動）を理解する |

**主要処理フロー**:
1. **71-73行目**: qfextension（クォータファイル拡張子）、tmpfil（テンポラリファイルパス）、hflag（人間可読フラグ）の定義
2. **75-81行目**: quotause構造体（ファイルシステムごとのクォータ情報をリンクドリストで管理）
3. **84-100行目**: 関数プロトタイプ宣言（getprivs/putprivs/readprivs/writeprivs等）

#### Step 3: quotacheckの処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | quotacheck.c | `sbin/quotacheck/quotacheck.c` | ファイルシステムスキャンのロジック、fileusage構造体（UID/GIDごとの使用量集計）、UFSスーパーブロック参照を理解する |

**主要処理フロー**:
1. **67-76行目**: sb_un/cg_un（スーパーブロック・シリンダグループ用バッファ）
2. **80-82行目**: DIPマクロ（UFS1/UFS2のdinode構造体アクセス抽象化）
3. **87-96行目**: fileusage構造体（UID/GIDごとのinode/ブロック使用量をハッシュテーブルで管理）

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

```
edquota (usr.sbin/edquota/edquota.c)
    |
    +-- main()
          +-- getprivs()          # 現在のクォータ値取得
          |     +-- quotactl(2)   # カーネルからクォータ読み出し
          +-- writeprivs()        # テンポラリファイル書き出し
          +-- editit()            # エディタ起動
          +-- readprivs()         # 編集結果読み込み
          +-- putprivs()          # クォータ値設定
                +-- quotactl(2)   # カーネルへクォータ書き込み

quotacheck (sbin/quotacheck/quotacheck.c)
    |
    +-- main()
          +-- fstab走査           # クォータ有効FSの特定
          +-- inode全スキャン     # 各inodeのUID/GID/サイズ集計
          |     +-- bread()       # ディスクブロック読み込み
          +-- fileusage集計       # UID/GIDごとの使用量ハッシュ
          +-- クォータDB更新      # quota.user/quota.group書き出し
```

### データフロー図

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

edquota:
ユーザ名/グループ名  --> getprivs() --> エディタ  --> putprivs() --> quota.user
                         (quotactl)     (対話編集)    (quotactl)    quota.group

quotacheck:
ファイルシステム      --> inodeスキャン --> fileusage集計 --> quota.user
(/etc/fstab)              (bread)         (ハッシュ)       quota.group
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| edquota.c | `usr.sbin/edquota/edquota.c` | ソース | クォータ編集コマンドのメイン処理 |
| quotacheck.c | `sbin/quotacheck/quotacheck.c` | ソース | クォータ整合性チェックコマンドのメイン処理 |
| preen.c | `sbin/quotacheck/preen.c` | ソース | ファイルシステムpreen処理 |
| quotacheck.h | `sbin/quotacheck/quotacheck.h` | ヘッダ | quotacheck共通定義 |
| pathnames.h | `usr.sbin/edquota/pathnames.h` | ヘッダ | パス定義 |
| quota.h | `sys/ufs/ufs/quota.h` | ヘッダ | クォータデータ構造定義（dqblk等） |
| edquota.8 | `usr.sbin/edquota/edquota.8` | マニュアル | edquotaコマンドのmanページ |
| quotacheck.8 | `sbin/quotacheck/quotacheck.8` | マニュアル | quotacheckコマンドのmanページ |
