Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
btrfs領域管理一代記
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
naota
September 23, 2017
Technology
1.3k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
btrfs領域管理一代記
naota
September 23, 2017
More Decks by naota
See All by naota
ファイルシステムの歴史: ジャーナリング編
naota
2
1.1k
DockerでGentooのテスト
naota
3
1.9k
Btrfsのころしかた(だったもの)
naota
0
1.1k
Btrfsの構造
naota
5
2.9k
Other Decks in Technology
See All in Technology
AI駆動開発におけるハーネスエンジニアリングの勘所
tsukuboshi
1
480
10年後、Engineering 行為を剥奪されるとして、わたしたちは、どう、何を創ればいいだろうか。 / If Engineering Is Taken Away in 10 Years, How and What Should We Create?
bitkey
PRO
1
220
Metadata - Section 2: Simple Metadata & Meta Tags
mohab1
0
110
ガチで放置できるClaude Code実行環境の作り方.pdf
lamaglama39
0
4.4k
Kiro Crewで「みのるん式」仕事術やってみた
minorun365
PRO
3
1k
AI × アーキテクト 第1・2章|生成AIの課題とアーキテクトの素養
daidaidai
1
230
古い指輪から広がった JAVA コミュニティ とのつながり
yamad
0
140
S3 Filesで挑む! 八戸せんべい汁の食べ頃問題
usanchuu
0
140
sue445's proposals 2026
sue445
0
130
dbt Semantic Layerで進めるenechainのデータ民主化
akizhou
1
210
Rustuna: Rustによる高速なOptuna実装
pfn
PRO
0
210
[EMNLP26] RIGEL: Self-Distilled Score Adaptation for Image and Video Captioning Evaluation
keio_smilab
PRO
0
110
Featured
See All Featured
Building Flexible Design Systems
yeseniaperezcruz
330
41k
Balancing Empowerment & Direction
lara
6
1.3k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
50
10k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
500
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.8k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.8k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.6k
How to Talk to Developers About Accessibility
jct
2
590
Joys of Absence: A Defence of Solitary Play
codingconduct
1
550
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
350
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.9k
Transcript
btrfs領域管理一代記 牛酪亭直太
Linuxファイルシステム戦国時代 • 台頭する新興FSたち ◦ 平成13(2001)年1月: ReiserFS, Linuxに入る ◦ 同6月: JFS
◦ 平成14(2001)年: XFS • そのころのFS: Ext3, XFS, ReiserFS ◦ Ext3はLinux古来の流れを組む由緒正しき FS ▪ ext1は, 文献上のみで知られ、実 (用的に存)在はしなかったと言われている ▪ ext3を刷新したext4の開発 ◦ XFSはSGIの流れを組む(Linuxでは)比較的新しいFS • ReiserFS ◦ 初めてジャーナリングを Linuxに持ちこんだ ◦ B+treeに様々なmetadataを保管
Btrfsの建国 • 平成18(2006)年: Reiser家「お家騒動」により, 開発中のReiser4は凋落 • Btrfs創設者: Chris Mason ◦
もともとSuSEでReiserFSの開発に関わる ◦ その後、OracleにてBtrfsを立ち上げ ◦ Fusion-IOを経て、現在はFacebook所属 • 平成19(2007)年, Btrfsの誕生 ◦ [ANNOUNCE] Btrfs: a copy on write, snapshotting FS ◦ B-trees, Shadowing, and Clones [Rodeh, ToS’07] による, CoW フレンドリーなB-tree
Btrfs七勇士と家臣団 • Btrfs七勇士 ◦ checksumによるデータ保護 ◦ snapshot ◦ subvolume ◦
複数デバイスサポート ◦ 透過的圧縮 ◦ send/recvを使った効率的差分バックアップ ◦ dedupe • Btrfsを支える関数総勢1791個 • 今日のお題 find_free_extent() ◦ 指定されたサイズの空き領域を探索する関数
find_free_extent()奇々怪々 • 行数482行の大関数 ◦ その半分近くを占める 259行の大ループ • 8つのgoto label, 22のgoto文
◦ 右図のような状態遷移 (単純な上下は省略) 大ループ
通常のFSのマッピング 通常のFSはファイルアドレスと ディスク上のアドレスを直接マッピング
Btrfsのマッピング: extent空間 • 複数デバイスに対応するため, ディスクに直接マッピングしにくい
Btrfsのマッピング: extent空間 • 複数デバイスに対応するため, ディスクに直接マッピングしにくい • extent空間という「仮想領域」を 中間にはさむ • extent上のBlock
Groupが, さらにディス クにマップされる
find_free_extent()の読解ポイント • free space cache treeを知る ◦ free spaceをメモリ上で管理する tree
• クラスタを知る ◦ cacheから条件に合う領域だけを集めた tree • “loop”変数に惑わされない ◦ 4つのstageと考える ◦ stageごとにallocation戦略が変わる • アロケーションの階層をイメージする ◦ クラスタからのalloc ◦ BlockGroupからクラスタへのrefill ◦ extent空間から新しいBlockGroupのalloc ◦ 最後の手段: クラスタなしのalloc
free space cache tree: 連続領域(extent)ノード • free space cache tree
◦ 空き領域の位置とサイズを管理する赤黒木 ◦ 各BlockGroupで一つ、メモリ上に構築 ◦ 構築するにはIOが必要 • ノード ◦ キー 空き領域の開始アドレス (BGの先頭からのオフセット ) ◦ bytes 空き領域のサイズ • 一つの連続した空き領域(extent)に対して、一つのノード
free space cache tree: bitmap • 断片化した領域を保持するには、多くのノードが必要になる ◦ 一連続領域に一ノードの弊害 •
ある程度断片化したところで、extentノードをbitmapノードに変換 • bitmapノードの開始位置は128MBにalignされる ◦ 結果的に、同じアドレスをキーとして "bitmapノード"と"extentノード"とが重複する ▪ (コードがめんどくなるんよ ) ◦ 128MB = 1つのbitmapでカバーする領域 ◦ BGが大きくても1GBなので、断片化しまくっても 8つのbitmapノードで覆うことができる
クラスタ • 各BGのcacheの, さらに上位のcache ◦ metadata と dataでそれぞれ1つ • cacheは,
offsetをキーとするため, サイズを条件とした探索ができない ◦ 赤黒木なのに線形探索 ◦ 効率化のため, 一定の条件に合う領域を「クラスタ」に集めておく • クラスタは可能なかぎり、extentノードだけで作られる ◦ bitmapノードは断片化しているため , allocが成功しにくい • できる限り, このクラスタからallocを行う
クラスタとmount option • BtrfsのSSD最適化 ◦ 2つのmount option: SSD, SSD_SPREAD •
mount optionによりクラスタ作成法が変わる ◦ SSD_SPREAD ▪ alloc_size + 2M の領域を見つけだす . それ未満の領域を全て無視 ◦ metadata ▪ alloc_size の領域を1つ確保 ▪ 最低成立量: SSD: 2MB, HDD 64K ◦ data: alloc_size の領域を1つ確保. 最低成立量なし
秘技loop二刀流 • 2つの”loop” ◦ gotoラベルのloop ◦ 変数のloop • 2つの"loop"は独立している •
goto loopは"見える"forループを回す ◦ continueのようなもの • loop変数は, "見えない"ループのカウンタ ◦ goto searchで”見える”forループの後から前に戻る時にインクリメント • ここからloop変数のことを”stage”と言いかえる ◦ stageごとに、alloc戦略が変わる
アロケーションの階級社会 1. CACHING_NOWAIT ◦ クラスタからalloc ◦ 適宜クラスタを作る ◦ cacheを待たない 2.
CACHING_WAIT ◦ NOWAITと同じ ◦ cacheを待つ 3. ALLOC_CHUNK ◦ 新しいBGを作る ◦ あとはNOWAIT 4. NO_EMPTY_SIZE ◦ 最終手段 ◦ クラスタを使わない
関数冒頭, そしてループに飛び越む • last_ptr = fetch_cluster_info(fs_info, space_info, &empty_cluster); ◦ last_ptrに「最後に使ったクラスタ」を読みこむ
◦ empty_clusterには、クラスタを作る時用にほしいクラスタサイズが入る • if (last_ptr->block_group) hint_byte = last_ptr->window_start; ◦ 最後に使っていたクラスタがあれば , 引数のalloc hintは無視! • goto have_block_group; ◦ Block Groupをlockしたら、一気に大ループのどまん中に飛び越む !!!
have_block_group: • このラベルの時点で、allocを試みるBlockGroupが決まっている • if (!block_group_cache_done(block_group)) cache_block_group(block_group, 0); ◦ cacheができていなければ、
cacheするスレッドを走らせる • btrfs_alloc_from_cluster(...) ◦ クラスタからのallocを試みる ◦ 必要な領域を取得できれば -> goto checks ◦ 取得できなければ, release_cluster へ
release_cluster:/refill_cluster • release_cluster: クラスタを解放するための場所 • btrfs_return_cluster_to_free_space(NULL, last_ptr); ◦ クラスタに確保していた空き領域情報をBlockGroupのcacheに返却 •
refill_cluster: BGからクラスタに領域を確保する場所 • btrfs_find_space_cluster() ◦ クラスタを作り直す ◦ クラスタを作ったら ▪ btrfs_alloc_from_cluster()で、できたてのクラスタから alloc ◦ 作れなかった or やっぱりクラスタから allocできなかったら ▪ クラスタを解放(クラスタからallocできない時用) ▪ goto loop して、次のBlockGroupへ
checks: / loop: • checks: allocがうまくいった時にgoto ◦ 領域の確認や, メモリ上での空き容量情報を更新する •
loop: allocがうまくいかなかった時に goto ◦ いくつか変数をresetし, BlockGroupを解放して, ループをまわり次の BlockGroupへ
ループの後 • allocする領域を見つけた / 全てのBGからallocをためし終わった • まだallocできてなければ、ここで次のstageを決める ◦ stage ==
CACHING_NOWAIT ▪ cacheをkickしたBGがあれば -> 次はCACHING_WAIT ▪ なければ -> ALLOC_CHUNK ◦ stage == ALLOC_CHUNK ▪ BlockGroup (=CHUNK)を新しく1つ作る ▪ 作れたら -> goto serachで、またループ (いま作ったBGからとれるはず) ▪ 作れなかった -> 次はNO_EMPTY_SIZE
NO_EMPTY_SIZEでのループ • 最終手段のalloc ◦ クラスタのサイズ下限を撤廃 : クラスタが前より成立しやすい ! ▪ とかなってんだけど、そもそも
if (loop >= LOOP_NO_EMPTY_SIZE) goto unclustered_alloc しててクラスタ作んない • btrfs_find_space_for_alloc() ◦ 直接cacheからのalloc ◦ allocできたら -> checks へ ◦ allocできなかった, かつ、 まだcache完成してなかったら -> cacheを待ってもう一度 ◦ allocできなかった -> goto loopでつぎのBG
アロケーションの階級社会 (再掲) 1. CACHING_NOWAIT ◦ クラスタからalloc ◦ 適宜クラスタを作る ◦ cacheを待たない
2. CACHING_WAIT ◦ NOWAITと同じ ◦ cacheを待つ 3. ALLOC_CHUNK ◦ 新しいBGを作る ◦ あとはNOWAIT 4. NO_EMPTY_SIZE ◦ 最終手段 ◦ クラスタを使わない
今日のまとめ • Ext*: 平家のようなFS • XFS: SeiwaGenjIのようなFS • ReiserFS: 織田信長のようなFS
Linuxファイルシステムを天下統一するのは誰なのか アロケータを把握したいま, みなさんはもはやbtrfsの家臣も同然. btrfsを盛り立てていきましょう
何度も同じループしすぎでは? • ぼくもそう思います • ループしてる間にほかの人が、領域解放した可能性はあるので・・・
ラベルとinvariant • search: “見える”ループを使って探索, stageの開始地点 • have_block_group: allocを試みるBlockGroupを決定した • release_cluster:
クラスタからallocできなかった. クラスタを解除 • refill_cluster: BGからクラスタに領域を確保 • unclustered_alloc: クラスタを使わずBG全体からallocを試みる ◦ BGはfragmentedしており、クラスタをとれない • checks: 候補となる領域を見つけた. 要求を満たすかを確認 • loop: 次のBGに移行 • out: 関数の終わり