feat: 가상화 문서들 추가
This commit is contained in:
@@ -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) 밖이라 인용할 줄도 없다. 게다가 네 이름의 나열은 기록 본문에 이미 코드블록으로 있어 그림으로 다시 그리면 중복이다. 그래서 자리로만 보이는 것 — 요구가 여섯 번 손이 바뀌어 내려간다는 것 — 만 남겼다."
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user