feat: 가상화 문서들 추가

This commit is contained in:
DongHyeonka
2026-09-10 08:54:05 +09:00
parent e9f6a93327
commit 43e1aadef0
695 changed files with 153404 additions and 12754 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,264 @@
{
"version": "1.1",
"id": "write-completion-boundaries",
"title": "fsync() 의 요구가 물리 storage 까지 내려가는 사슬",
"question": "게스트가 fsync() 를 부르면 그 요구는 어느 계층까지, 몇 번 손이 바뀌어 내려가야 하는가",
"type": "flow",
"direction": "TB",
"audience": [
"가상 머신 위에서 데이터베이스를 돌리며 durability 를 따지는 사람",
"완료 응답이 무엇을 보장하는지 가르려는 사람"
],
"summary": "게스트 PostgreSQL 의 fsync() 요구는 게스트 파일시스템과 게스트 Block Layer 에서 FLUSH 등으로 바뀌고 virtio-blk 와 QEMU / Backend, Host Storage Stack 을 지나 Physical Storage 까지 전달되어야 한다.",
"alt": "PostgreSQL 의 fsync() 가 Guest Filesystem, Guest Block Layer, virtio-blk, QEMU / Backend, Host Storage Stack 을 차례로 지나 Physical Storage 에 닿는 위에서 아래로 읽는 흐름도.",
"long_description": "위에서 아래로 읽는다. 맨 위 PostgreSQL 이 fsync() 를 부르고 그 요구가 Guest Filesystem 으로 내려간다. Guest Block Layer 에서 FLUSH 등의 요청으로 바뀌고, virtio-blk 를 지나 VM 경계를 넘어 QEMU / Backend 로 간다. 거기서 Host Storage Stack 을 지나 맨 아래 Physical Storage 까지 그 의미가 전달되어야 완료가 성립한다. 여섯 번 손이 바뀌는 동안 한 곳이라도 그 의미를 지키지 않으면 게스트가 받은 완료 응답이 거짓이 된다. write() 완료와 writeback 완료, fsync/flush 완료, 전원 장애에도 안전한 durability 가 서로 다르다는 구분은 본문의 코드블록이 맡는다.",
"source_context": {
"document": "docs/virtualization/final/document.md",
"document_sha256": "181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd",
"anchor": {
"kind": "heading",
"value": "150. `fsync()`가 필요한 이유",
"line": 6723
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "이 절이 주장하는 것은 요구 하나가 한 방향으로 여러 계층을 지나야 완료가 된다는 것이다. sequence 는 참여자마다 생명선을 세우고 요청과 응답을 짝지어 세우는데 이 절에는 돌아오는 응답이 적혀 있지 않아 생명선이 전부 빈 세로줄이 된다. comparison 은 write 와 fsync 를 나란히 놓는 그림이라 「어디까지 내려가야 하는가」라는 자리의 문제가 지워진다.",
"focus_node": "physical-storage"
},
"groups": [],
"nodes": [
{
"id": "postgresql",
"label": "PostgreSQL",
"kind": "service",
"role": "source",
"shape": "box",
"details": [
"write()",
"fsync()"
],
"description": "필요한 시점에 fsync() 를 불러 영속성 경계까지 반영을 요청하는 게스트 프로세스.",
"evidence": [
{
"start_line": 6742,
"end_line": 6742
},
{
"start_line": 6726,
"end_line": 6734
}
],
"assumption": false
},
{
"id": "guest-filesystem",
"label": "Guest Filesystem",
"kind": "service",
"role": "service",
"shape": "box",
"description": "fsync() 요구를 처음 받는 게스트 파일시스템.",
"evidence": [
{
"start_line": 6746,
"end_line": 6746
}
],
"assumption": false
},
{
"id": "guest-block-layer",
"label": "Guest Block Layer",
"kind": "service",
"role": "service",
"shape": "box",
"description": "요구를 FLUSH 등의 block 요청으로 바꾸는 계층.",
"evidence": [
{
"start_line": 6749,
"end_line": 6751
}
],
"assumption": false
},
{
"id": "virtio-blk",
"label": "virtio-blk",
"kind": "service",
"role": "service",
"shape": "box",
"description": "그 요청을 VM 경계 너머로 옮기는 게스트 driver.",
"evidence": [
{
"start_line": 6753,
"end_line": 6753
}
],
"assumption": false
},
{
"id": "qemu-backend",
"label": "QEMU / Backend",
"kind": "service",
"role": "service",
"shape": "box",
"description": "요청을 받아 호스트 쪽 파일 I/O 나 block I/O 로 잇는 자리.",
"evidence": [
{
"start_line": 6756,
"end_line": 6756
},
{
"start_line": 6686,
"end_line": 6686
}
],
"assumption": false
},
{
"id": "host-storage-stack",
"label": "Host Storage Stack",
"kind": "service",
"role": "service",
"shape": "box",
"description": "호스트 Page Cache 와 파일시스템, Block Layer 가 놓인 구간.",
"evidence": [
{
"start_line": 6759,
"end_line": 6759
},
{
"start_line": 6688,
"end_line": 6692
}
],
"assumption": false
},
{
"id": "physical-storage",
"label": "Physical Storage",
"kind": "store",
"role": "sink",
"shape": "box",
"emphasis": "primary",
"description": "요구가 여기까지 전달되어야 정전 이후 생존을 말할 수 있다.",
"evidence": [
{
"start_line": 6762,
"end_line": 6765
},
{
"start_line": 6729,
"end_line": 6729
}
],
"assumption": false
}
],
"edges": [
{
"id": "app-to-guest-fs",
"from": "postgresql",
"to": "guest-filesystem",
"label": "fsync()",
"kind": "control",
"style": "solid",
"order": 1,
"evidence": [
{
"start_line": 6744,
"end_line": 6746
}
],
"assumption": false
},
{
"id": "guest-fs-to-block-layer",
"from": "guest-filesystem",
"to": "guest-block-layer",
"label": "",
"kind": "control",
"style": "solid",
"order": 2,
"evidence": [
{
"start_line": 6746,
"end_line": 6749
}
],
"assumption": false
},
{
"id": "block-layer-to-virtio",
"from": "guest-block-layer",
"to": "virtio-blk",
"label": "FLUSH 등",
"kind": "control",
"style": "solid",
"order": 3,
"evidence": [
{
"start_line": 6751,
"end_line": 6753
}
],
"assumption": false
},
{
"id": "virtio-to-qemu",
"from": "virtio-blk",
"to": "qemu-backend",
"label": "",
"kind": "control",
"style": "solid",
"order": 4,
"evidence": [
{
"start_line": 6753,
"end_line": 6756
}
],
"assumption": false
},
{
"id": "qemu-to-host-stack",
"from": "qemu-backend",
"to": "host-storage-stack",
"label": "",
"kind": "control",
"style": "solid",
"order": 5,
"evidence": [
{
"start_line": 6756,
"end_line": 6759
}
],
"assumption": false
},
{
"id": "host-stack-to-physical",
"from": "host-storage-stack",
"to": "physical-storage",
"label": "",
"kind": "control",
"style": "solid",
"order": 6,
"evidence": [
{
"start_line": 6759,
"end_line": 6765
}
],
"assumption": false
}
],
"legend": [],
"metadata": {
"rationale": "component-flow 를 고른 이유는 이 절이 답하는 물음이 「fsync() 의 요구가 어디까지 내려가야 하는가」이기 때문이다. 앞뒤 절이 대는 사실 가운데 그리지 않은 것이 있다. 「write · writeback · fsync/flush · 전원 장애 생존」 네 완료 경계를 이 사슬 위에 표시하려 했으나 SSOT 는 §148 에서 네 이름을 나열할 뿐 writeback 완료와 fsync/flush 완료가 이 사슬의 어느 칸에서 성립하는지는 정하지 않았고, §148 자체가 이 앵커의 준비된 문맥(§149~§151) 밖이라 인용할 줄도 없다. 게다가 네 이름의 나열은 기록 본문에 이미 코드블록으로 있어 그림으로 다시 그리면 중복이다. 그래서 자리로만 보이는 것 — 요구가 여섯 번 손이 바뀌어 내려간다는 것 — 만 남겼다."
}
}