Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Operating Systems: Three Easy Pieces, Chapter 4...
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Arata
July 12, 2026
3
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Operating Systems: Three Easy Pieces, Chapter 49 / Sun's Network File System (NFS)
Arata
July 12, 2026
More Decks by Arata
See All by Arata
デコンパイラ研究調査
arata_nvm
1
14
コンパイラ基盤を支える言語たち
arata_nvm
1
71
LLVMのDSL”TableGen”向け言語サーバーの開発
arata_nvm
0
24
5分でわかるPage-Fault Weird Machine
arata_nvm
2
350
eBPFを用いたAndroid向けデバッガ「eDBG」のx86_64 Linuxへの移植
arata_nvm
0
22
Pythonのcopy-and-patch JITの実装を読む
arata_nvm
0
150
eBPFを使った動的解析手法
arata_nvm
1
790
カーネルハック実験の振り返り
arata_nvm
1
61
Improving LLVM Backend Development with a New TableGen Language Server
arata_nvm
0
55
Featured
See All Featured
Site-Speed That Sticks
csswizardry
13
1.2k
Between Models and Reality
mayunak
4
360
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
Code Review Best Practice
trishagee
74
20k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
How to build a perfect <img>
jonoalderson
1
5.8k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
180
Joys of Absence: A Defence of Solitary Play
codingconduct
1
410
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
300
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
200
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
310
Transcript
Sun’s Network File System (NFS) Operating Systems: Three Easy Pieces,
Chapter 491 安藤 慎 システムセキュリティ研究室 ゼミ / 2026 年 7 月 10 日 1https://pages.cs.wisc.edu/~remzi/OSTEP/dist-nfs.pdf
はじめに 話すこと 1. 分散ファイルシステムとは 2. NFS の設計、プロトコル 3. クライアントサイドの高速化 4.
サーバーサイドの高速化 1 / 28
はじめに 分散ファイルシステムとは ネットワーク越しにサーバ上のファイルへアクセスする仕組み Client 0 Client 1 Client 2 Client
3 Network Server RAID なぜローカルディスクを使わないのか? • データの共有: どのマシンからでも同じファイルシステムが見える • 集中管理: バックアップなどをサーバ側でまとめて行える • 物理的セキュリティ: サーバを施錠された部屋に置ける 2 / 28
はじめに 分散ファイルシステムの構成 クライアントサイドファイルシステムとファイルサーバが協調する Client Application Client-side File System ↓ ↑
Networking Layer ↓ ↑ File Server Disks 透過性 (Transparency) アプリからはローカルディスクと同じように 標準的なシステムコールでアクセスできる 3 / 28
NFS の概要 NFS とは Sun Microsystems が 1980 年代に開発した分散ファイルシステム 特徴:
オープンプロトコル • クライアント・サーバ間のメッセージ形式だけを仕様として公開 • 誰でも互換性のある NFS サーバを実装・販売できる • NetApp, EMC(Dell), IBM など多くの企業が参入し、NFS の成功要因に なった 本章では標準化された NFSv21を扱う 1https://datatracker.ietf.org/doc/html/rfc1094 4 / 28
NFS の概要 設計目標: 単純かつサーバクラッシュから高速に回復 NFSv2 の主目標: simple and fast server
crash recovery 複数クライアント・単一サーバの環境ではサーバが落ちるとシステム 全体が動かなくなる → サーバが落ちてもすぐ復帰できることがプロトコル設計の中心 NFSv41や Andrew File System (Chapter 50)2で複数サーバーに冗長化する方向に発展する 1https://www.rfc-editor.org/rfc/rfc8881.html 2https://pages.cs.wisc.edu/~remzi/OSTEP/dist-afs.pdf 5 / 28
NFS の概要 余談: なぜサーバは落ちるのか • 停電(電源が戻るまで再起動できない) • バグ(数十万〜数百万行のコードなら、良いソフトでも数百〜数千 行に数個はバグがある) •
メモリリーク(小さなリークでもいずれメモリが尽きる) • ネットワーク分断(実際には生きているのに、通信できず落ちてい るように見える) 6 / 28
ステートレス 回復を速くする鍵: ステートレス NFSv2 はステートレスなプロトコルとして設計された ステートレス サーバがクライアントの状態(オープン中のファイル、 ファイルポインタの位置など)を一切記憶しない • 各リクエストに、処理に必要なすべての情報を含める
• サーバはクラッシュしてもただ再起動するだけでよい • クライアントはリトライすればよい 7 / 28
ステートレス ステートフルだと何が困るのか (1) Linux で open() が返すファイルディスクリプタを考える c 1 2
3 4 5 6 char buffer[MAX]; int fd = open("foo", O_RDONLY); // fdを取得 read(fd, buffer, MAX); // fd経由でfooを読む read(fd, buffer, MAX); // もう一度読む ... close(fd); // ファイルを閉じる 素朴な設計: サーバで open() をそのまま実行してディスクリプタを返す → fd はクライアント・サーバ間の共有状態になる 8 / 28
ステートレス ステートフルだと何が困るのか (2) サーバがクラッシュした場合 • 再起動後、fd がどのファイルを指していたか分からない • 復旧には回復プロトコルが必要になり、複雑化する クライアントがクラッシュした場合
• close() されないので、サーバ側のディスクリプタを閉じられない • サーバはクライアントの死を検知する必要がある → NFS の設計者はステートレスなアプローチを選んだ 9 / 28
NFSv2 プロトコル ステートレスなプロトコルをどう定義するか ステートレスなプロトコルで POSIX API をサポートするには? 操作対象を一意に指す識別子(ファイルハンドル, FH)を毎回伝える ファイルハンドルは以下から構成される:
• ボリューム識別子: どのファイルシステムか • inode 番号: そのファイルシステム内のどのファイルか • 世代番号: inode 番号の再利用時にインクリメント 10 / 28
NFSv2 プロトコル 主なプロトコルメッセージ1 メッセージ 操作 LOOKUP ファイル名からファイルハンドルを得る READ 指定範囲を読む WRITE
指定範囲に書く GETATTR 属性を取得 CREATE ファイルの作成 REMOVE ファイルの削除 MKDIR ディレクトリの作成 RMDIR ディレクトリの削除 READDIR エントリ一覧を取得 このほか SETATTR, ROOT, READLINK, WRITECACHE, RENAME, LINK, SYMLINK, STATFS が定義されている 1https://datatracker.ietf.org/doc/html/rfc1094#section-2.2 11 / 28
NFSv2 プロトコル ファイル読み込みの流れ Client-side File System File Server open("/foo") LOOKUP(ROOT(),
"foo") ルートで“foo”を探す FH, ファイル属性 read(fd, ...) READ(FH, offset=0, count=MAX) FH からファイルを特定し データを読む データ, ファイル属性 close(fd) クライアントで保持していたデータを削除 (サーバとの通信は不要) • ファイルポインタや fd→FH の対応はクライアント側が管理する • 各リクエストは処理に必要な情報をすべて含む • ファイル属性はキャッシュで活用される(後述) 12 / 28
クラッシュへの対処 サーバの無応答にどう対処するか サーバーへリクエストを送っても返事が来ないことがある Case 1: リクエスト消失 Client Server リクエスト ✗
Case 2: サーバダウン Client Server (ダウン中) リクエスト ✗ Case 3: 応答が消失 Client Server リクエスト 処理 応答 ✗ → クライアントには 3 つのケースの区別がつかない 13 / 28
クラッシュへの対処 対処法: タイムアウトとリトライ NFSv2 では以下の方法で対処する: 1. リクエスト送信時にタイマーをセット 2. タイマーが切れる前に応答が来たら →
OK 3. 応答が来ないままタイマーが切れたら → 同じリクエストを再送 ほとんどの操作が冪等(Idempotent)なためリトライで済む 冪等 操作を複数回実行した結果と、1 回実行した結果が同じ 14 / 28
クラッシュへの対処 NFS で頻出する操作は冪等 • LOOKUP, READ, GETATTR: 読むだけなので自明に冪等 • WRITE:
データ・サイズに加えてオフセットを含むので冪等(同じ位置 が同じデータで上書きされるだけ) 15 / 28
クラッシュへの対処 例外: MKDIR , CREATE , REMOVE などは冪等でない 1. クライアントが
MKDIR をリクエスト 2. サーバが MKDIR を実行し成功したが、応答が消失した(Case 3) 3. クライアントがリクエストを再送 4. ディレクトリは既に存在するので「失敗」が返る MKDIR の意味論を変えれば冪等にできる1が NFS の設計者はしなかった 完璧は善の敵(Voltaire’s Law) コーナーケースをすべて潰すより、重要なケースをカバーして設計を単純に 保つ方が良い 1「既に存在していても成功を返す」ようにすればよい 16 / 28
クラッシュへの対処 補足: 再送で操作が再実行されることを防ぐ手法1 サーバーが「初回リクエスト」と「再送されたリクエスト」を区別できないこと が原因。再送は同じ XID(トランザクション ID)を持つことを利用する。 Client Server MKDIR
(xid=42) 実行して成功、結果をキャッシュ 応答 ✗ タイムアウト MKDIR (xid=42) を再送 キャッシュヒット、mkdir は再実行しない 応答 「成功」を受け取る 1https://datatracker.ietf.org/doc/html/rfc1813#section-4.5 17 / 28
クライアントサイドキャッシュ 性能改善: クライアントサイドキャッシュ ネットワーク通信は遅いため、クライアントでファイルの内容を キャッシュ・バッファリングする 読み込み 初回だけ通信し、以降はキャッシュから即座に返す 書き込み バッファに書いて WRITE
はすぐ成功を返し、あとでまとめて サーバに書き込む → キャッシュ一貫性問題が生まれる 18 / 28
クライアントサイドキャッシュ キャッシュ一貫性問題 ①: 更新可視性 C2 が F の内容を上書きしたが、その変更はまだサーバーに送られて いない C2
cache: F[v2] C3 cache: (空) Server S disk: F[v1] 1. write がバッファに 留まり未送信 2. read → F[v1] ① 更新可視性 C2 の更新は、いつ他のクライアントから見えるようになる? 19 / 28
クライアントサイドキャッシュ キャッシュ一貫性問題 ②: 古いキャッシュ その後、C2 の更新がサーバに書き戻された C1 cache: F[v1] C2
cache: F[v2] Server S disk: F[v2] 書き戻し read → キャッシュの F[v1] を 読んでしまう ② 古いキャッシュ サーバは最新だが、C1 は手元の古いコピーを読み続ける 20 / 28
クライアントサイドキャッシュ NFSv2 における解決策 ① 更新可視性 → flush-on-close • ファイル更新後 close()
されたら、キャッシュ内の更新を すべてサーバへ送る • → その後に他クライアントがアクセスすれば最新版が見える ② 古いキャッシュ → 使う前に GETATTR で最新か確認 • キャッシュされたデータを使う前にサーバへ GETATTR を送り、 ファイルの最終更新時刻を取得 • キャッシュ取得時より新しければキャッシュを無効化して取り直す • LOOKUP, READ 等が返すファイル属性を GETATTR の代わりに利用できる 21 / 28
クライアントサイドキャッシュ 新たな問題: 膨大な GETATTR リクエスト 解決策を実装してみるとサーバが GETATTR リクエストで溢れてしまった • ほとんどのファイルは
1 つのクライアントからしか使われないのに、 アクセスするたびにファイルが変更されたか確認し続ける •「良い工学の原則はコモンケースに最適化すること」に反する 対策: 属性キャッシュ → 一定時間(Sun の実装では 3 秒)GETATTR なしでキャッシュを使って よい 22 / 28
クライアントサイドキャッシュ NFS のキャッシュ一貫性を評価する flush-on-close の問題 短命な一時ファイルもサーバへ送られてしまう 属性キャッシュの問題 キャッシュが切れていないせいで古い版が返ることがある → 実装の詳細が観測可能な意味論を定義してしまった
複数のクライアント間で属性キャッシュの整合性を確保するには、noac マウントオプションを使用 してください。NFS プロトコルは、アプリケーションレベルでの何らかの同期処理を行わない限り、 真のクラスタファイルシステムキャッシュ一貫性を保証するように設計されていません。1 1https://linux.die.net/man/5/nfs 23 / 28
サーバサイドの書き込み サーバ側の書き込みバッファリング サーバはメモリが潤沢なことが多く、クライアントと同様にキャッ シュ・バッファリングをする サーバは書き込みを永続ストレージに書くまで WRITE に成功を返しては ならない メモリに置いただけで成功を返した場合を考えてみる: c
1 2 3 write(fd, a_buffer, size); // 1ブロック目をaで上書き write(fd, b_buffer, size); // 2ブロック目をbで上書き write(fd, c_buffer, size); // 3ブロック目をcで上書き 24 / 28
サーバサイドの書き込み サーバ側の書き込みバッファリング (Cont’d) 1. 1 つ目の WRITE: ディスクに書いて成功を返す 2. 2
つ目の WRITE: メモリに置いて成功を返す→ 直後にサーバがクラッシュ 3. 3 つ目の WRITE: サーバはすぐ再起動し、ディスクに書いて成功を返す クライアントには全リクエストが成功したように見えるが、2 ブロッ ク目だけ元の内容のままになってしまう 元のファイル 期待する結果 実際 xxxxxxxxxxxxxxxxxx aaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaa yyyyyyyyyyyyyyyyyy → bbbbbbbbbbbbbbbbbb → yyyyyyyyyyyyyyyyyy zzzzzzzzzzzzzzzzzz cccccccccccccccccc cccccccccccccccccc 25 / 28
サーバサイドの書き込み 対策と代償 • 書き込みを永続化してから成功を返せば、クライアントのリトライ で安全になる • ただし書き込み性能がボトルネックになる 高速に書ける NFS サーバ
Network Appliance などはこれを目標に創業した • バッテリバックアップ付きメモリに書いて応答 • 高速に書き込めるよう設計された LFS1 (WAFL) 1https://pages.cs.wisc.edu/~remzi/OSTEP/file-lfs.pdf 26 / 28
サーバサイドの書き込み まとめ • NFSv2 の設計目標は単純かつサーバクラッシュから高速に回復 ‣ ステートレスプロトコル: サーバは再起動するだけでよい ‣ 冪等な操作:
クライアントはただリトライすればよい • クライアントサイドキャッシュはキャッシュ一貫性問題を引き起こす ‣ flush-on-close、属性キャッシュでアドホックに解決(時々変な挙動を起 こす) • サーバの書き込みでは永続化してから成功を返さねばならない 27 / 28
サーバサイドの書き込み 余談: ジョーク集 • NFSv2 の仕様書(RFC 1094)について 「恐怖の仕様書。読むなら読むことでお金をもらえるときだけにせよ。高給だといい ね。Cash money!」
• NFSv4 の設計論文について 「間違いなく史上最も文学的な NFS 論文」 • The AWK Programming Language の共著者 Weinberger に「awk の W です」と自己紹介 され、 「awk 大好きです! 特にこの本が!」と返したら「その本は Kernighan が書 いた」と言われた 28 / 28