# 機能設計書 13-NFS（クライアント/サーバ）

## 概要

本ドキュメントは、FreeBSDのNetwork File System（NFS）クライアントおよびサーバ機能の設計を記載する。NFSはネットワーク経由でリモートファイルシステムを透過的にマウント・共有する機構であり、NFSv3およびNFSv4.xプロトコルに対応する。

### 本機能の処理概要

**業務上の目的・背景**：NFSはネットワーク環境においてファイル共有を実現するための標準プロトコルであり、複数のサーバ・クライアント間でデータを効率的に共有する必要がある環境（データセンター、クラスタ構成等）において不可欠な機能である。

**機能の利用シーン**：ネットワーク上の共有ストレージへのアクセス、ホームディレクトリの共有、ディスクレスブート時のルートファイルシステムマウント、バックアップサーバへのリモートマウントなど。

**主要な処理内容**：
1. NFSクライアントによるリモートファイルシステムのマウント
2. NFSサーバによるローカルファイルシステムのエクスポート
3. RPCベースの通信プロトコル処理
4. NFSv3ステートレスファイルアクセス
5. NFSv4ステートフルオープン・委譲（delegation）
6. ファイルロック（NLM - Network Lock Manager）
7. クライアント側キャッシュ（属性キャッシュ、データキャッシュ）
8. Kerberos認証（RPCSEC_GSS）連携
9. nfsiodによる非同期I/O

**関連システム・外部連携**：TCP/IPプロトコルスタック経由で通信する。Kerberos認証（Heimdal）との連携、rpcbind(8)によるポートマッピング。

**権限による制御**：エクスポート設定（/etc/exports）によりアクセス可能なホスト・ネットワークを制御。NFSv4ではACLベースのアクセス制御。root_squashによるroot権限マッピング。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに直接関連する画面なし |

## 機能種別

データ連携 / ネットワークファイルアクセス

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| サーバホスト名 | char* | Yes | NFSサーバのホスト名またはIPアドレス | 名前解決可能であること |
| エクスポートパス | char* | Yes | サーバ上のエクスポートディレクトリパス | パス形式の妥当性 |
| マウントポイント | char* | Yes | クライアント側のマウント先 | ディレクトリの存在確認 |
| NFSバージョン | int | No | 使用するNFSプロトコルバージョン（3 or 4） | 3, 4 |
| マウントオプション | char* | No | soft/hard, intr, tcp/udp等 | 有効なオプション |

### 入力データソース

- mount_nfs(8) コマンドからのユーザ入力
- /etc/fstab設定ファイル
- RPCメッセージ（ネットワーク経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ファイルデータ | バイトストリーム | リモートファイルの内容 |
| ファイル属性 | struct vattr | リモートファイルのメタデータ |
| ディレクトリエントリ | struct dirent | リモートディレクトリ一覧 |
| ファイルハンドル | nfs_fh | サーバ側ファイルの一意識別子 |

### 出力先

- VFS層を介したユーザ空間アプリケーション
- クライアント側バッファキャッシュ

## 処理フロー

### 処理シーケンス

```
1. マウント処理（クライアント側）
   └─ サーバ名解決 → RPCポートマップ問い合わせ → MOUNT RPC → ルートファイルハンドル取得
2. ファイルアクセス（クライアント側）
   └─ VFS要求 → NFS RPC生成 → ネットワーク送信 → 応答受信 → データ返却
3. エクスポート処理（サーバ側）
   └─ /etc/exports読み込み → mountd起動 → nfsd起動 → RPC応答待ち
4. ファイルロック
   └─ NLM RPC → サーバ側ロック管理 → 応答返却
```

### フローチャート

```mermaid
flowchart TD
    A[クライアント: mount_nfs] --> B[RPC: MOUNT]
    B --> C[サーバ: mountd]
    C --> D[ファイルハンドル返却]
    D --> E[クライアント: VFSマウント完了]
    E --> F[ファイルI/O要求]
    F --> G[NFS RPC生成]
    G --> H[ネットワーク送信]
    H --> I[サーバ: nfsd処理]
    I --> J[ローカルVFS操作]
    J --> K[応答返却]
    K --> L[クライアント: データ返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-13-01 | hard/softマウント | hardマウントはサーバ無応答時に無限リトライ、softは一定回数でエラー返却 | マウントオプション |
| BR-13-02 | 属性キャッシュ | ファイル属性はクライアント側でキャッシュされ、一定期間後に再検証 | ファイルアクセス時 |
| BR-13-03 | NFSv4委譲 | サーバが読み取り/書き込み委譲をクライアントに付与し、サーバ問い合わせを削減 | NFSv4使用時 |
| BR-13-04 | ステートレスI/O | NFSv3ではサーバはクライアント状態を保持しない | NFSv3使用時 |

### 計算ロジック

- 属性キャッシュタイムアウト: acregmin〜acregmax（ファイル）、acdirmin〜acdirmax（ディレクトリ）
- I/Oサイズ: rsize/wsizeパラメータ（デフォルト65536バイト）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| リモートファイル読み取り | - | SELECT(RPC) | READ RPCによるリモートデータ取得 |
| リモートファイル書き込み | - | UPDATE(RPC) | WRITE RPCによるリモートデータ更新 |
| ファイル作成 | - | INSERT(RPC) | CREATE RPCによるリモートファイル作成 |

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

NFSはリモートファイルシステムへのRPC呼び出しであるため、ローカルデータベースへの直接操作は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ETIMEDOUT | タイムアウト | サーバ無応答 | ネットワーク確認、hardマウント時は自動リトライ |
| ESTALE | ステールハンドル | サーバ側でファイルが削除/再作成 | ファイルハンドル再取得 |
| EACCES | 権限エラー | エクスポート設定不一致 | /etc/exports確認 |
| ERPCMISMATCH | RPCエラー | プロトコルバージョン不一致 | バージョン指定確認 |

### リトライ仕様

hardマウント時はサーバ応答があるまで無限リトライ（intr指定時はシグナルで中断可能）。softマウント時はretransパラメータ回数までリトライ後エラー返却。

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

NFSv3はステートレスプロトコルのため、トランザクション管理はサーバ側ファイルシステムに依存する。NFSv4ではcompound操作によりアトミック性を一部提供。書き込みの永続性はCOMMIT RPCにより保証。

## パフォーマンス要件

- 非同期I/O（nfsiod）によるリクエストパイプライニング
- クライアント側バッファキャッシュによる読み取り性能向上
- TCPコネクション多重化
- NFSv4.1セッション・pNFSによるパラレルアクセス

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

- AUTH_SYS（UID/GIDベース）認証
- RPCSEC_GSS / Kerberos認証によるセキュアなアクセス
- エクスポート設定によるホスト/ネットワーク制限
- root_squash（rootアクセスのnobodyマッピング）
- NFSv4 ACLによるファイルレベルアクセス制御

## 備考

- FreeBSDはNFSv3およびNFSv4.x（4.0, 4.1, 4.2）をサポート
- サーバ側デーモン: nfsd(8), mountd(8), rpcbind(8)
- クライアント側デーモン: nfsiod(8)
- NFSv4.1のpNFS（Parallel NFS）はサーバ側未サポートの場合あり

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | nfs.h | `sys/fs/nfsclient/nfs.h` | NFSクライアント側データ構造 |
| 1-2 | nfsmount.h | `sys/fs/nfsclient/nfsmount.h` | NFSマウント構造体 |
| 1-3 | nfsnode.h | `sys/fs/nfsclient/nfsnode.h` | NFSノード構造体 |
| 1-4 | nfsproto.h | `sys/fs/nfs/nfsproto.h` | NFSプロトコル定義（RPC番号、定数） |

**読解のコツ**: NFSコードはクライアント（sys/fs/nfsclient/）、共通（sys/fs/nfs/）、サーバ（sys/fs/nfsserver/）の3ディレクトリに分離されている。ファイル名のプレフィクスで判別する（nfs_cl* = クライアント、nfs_nfsd* = サーバ）。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | nfs_clvfsops.c | `sys/fs/nfsclient/nfs_clvfsops.c` | NFSクライアントのVFS操作 |

**主要処理フロー**:
1. **123行目**: nfs_mount関数の宣言
2. **125行目**: nfs_unmount関数の宣言
3. **135-156行目**: nfs_vfsops構造体の定義とVFS_SET登録

#### Step 3: クライアント側vnode操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | nfs_clvnops.c | `sys/fs/nfsclient/nfs_clvnops.c` | NFSクライアントのvnode操作 |
| 3-2 | nfs_clbio.c | `sys/fs/nfsclient/nfs_clbio.c` | クライアント側バッファI/O |

#### Step 4: RPC通信層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | nfs_clrpcops.c | `sys/fs/nfsclient/nfs_clrpcops.c` | クライアント側RPC操作 |
| 4-2 | nfs_commonkrpc.c | `sys/fs/nfs/nfs_commonkrpc.c` | 共通RPCトランスポート |

#### Step 5: サーバ側を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | nfs_nfsdserv.c | `sys/fs/nfsserver/nfs_nfsdserv.c` | NFSサーバ側RPC処理 |
| 5-2 | nfs_nfsdport.c | `sys/fs/nfsserver/nfs_nfsdport.c` | サーバ側ポート管理 |

#### Step 6: ユーザ空間ツール

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | mount_nfs.c | `sbin/mount_nfs/mount_nfs.c` | mount_nfsコマンド |
| 6-2 | nfsiod.c | `sbin/nfsiod/nfsiod.c` | NFS非同期I/Oデーモン |

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

```
mount_nfs(8)
    │
    └─ kernel: nfs_mount()（nfs_clvfsops.c）
           │
           ├─ RPC通信（nfs_commonkrpc.c）
           │      └─ TCP/IP → サーバ接続
           │
           └─ ルートファイルハンドル取得

VFS I/O要求
    │
    ├─ nfs_clvnops.c（vnode操作）
    │      ├─ nfs_read() / nfs_write()
    │      └─ nfs_lookup() / nfs_readdir()
    │
    ├─ nfs_clbio.c（バッファI/O）
    │
    ├─ nfs_clrpcops.c（RPC呼び出し）
    │
    └─ nfs_commonkrpc.c → TCP/IPスタック → ネットワーク

サーバ側:
    nfsd → nfs_nfsdserv.c → ローカルVFS操作 → 応答送信
```

### データフロー図

```
[クライアント側]                [ネットワーク]          [サーバ側]

ユーザI/O ──▶ NFS vnode ops    ──RPC──▶    nfsd
              ↓                                        ↓
              nfs_clbio.c                        ローカルVFS
              ↓                                        ↓
              nfs_clrpcops.c   ◀─RPC応答─    nfs_nfsdserv.c
              ↓
              データ返却
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| nfs_clvfsops.c | `sys/fs/nfsclient/nfs_clvfsops.c` | ソース | クライアントVFS操作 |
| nfs_clvnops.c | `sys/fs/nfsclient/nfs_clvnops.c` | ソース | クライアントvnode操作 |
| nfs_clbio.c | `sys/fs/nfsclient/nfs_clbio.c` | ソース | クライアントバッファI/O |
| nfs_clrpcops.c | `sys/fs/nfsclient/nfs_clrpcops.c` | ソース | クライアントRPC操作 |
| nfs_clstate.c | `sys/fs/nfsclient/nfs_clstate.c` | ソース | NFSv4状態管理 |
| nfs_commonkrpc.c | `sys/fs/nfs/nfs_commonkrpc.c` | ソース | 共通RPC通信 |
| nfs_commonsubs.c | `sys/fs/nfs/nfs_commonsubs.c` | ソース | 共通サブルーチン |
| nfsproto.h | `sys/fs/nfs/nfsproto.h` | ヘッダ | NFSプロトコル定義 |
| nfs_nfsdserv.c | `sys/fs/nfsserver/nfs_nfsdserv.c` | ソース | サーバRPC処理 |
| nfs_nfsdport.c | `sys/fs/nfsserver/nfs_nfsdport.c` | ソース | サーバポート管理 |
| nfs_nfsdcache.c | `sys/fs/nfsserver/nfs_nfsdcache.c` | ソース | サーバ応答キャッシュ |
| mount_nfs.c | `sbin/mount_nfs/mount_nfs.c` | ソース | mount_nfsコマンド |
| nfsiod.c | `sbin/nfsiod/nfsiod.c` | ソース | NFS非同期I/Oデーモン |
