feat: 가상화 문서들 추가
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,338 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "guest-block-io-to-virtqueue",
|
||||
"title": "게스트의 write() 가 virtqueue 에 실리기까지",
|
||||
"question": "게스트 애플리케이션의 write() 는 virtqueue 에 실리기 전에 게스트의 어느 계층을 어떤 순서로 지나는가",
|
||||
"type": "flow",
|
||||
"direction": "TB",
|
||||
"audience": [
|
||||
"게스트에서 본 저장소 지연을 계층별로 가르려는 사람",
|
||||
"virtio-blk 경로를 처음 읽는 사람"
|
||||
],
|
||||
"summary": "게스트 애플리케이션의 write() 는 VFS 와 ext4/XFS, Guest Page Cache, Guest Block Layer, /dev/vda, virtio-blk Frontend 를 차례로 지나 virtqueue 에 실린다.",
|
||||
"alt": "게스트 사용자 공간의 PostgreSQL/Keycloak 에서 시작한 write() 가 게스트 커널의 VFS, ext4/XFS, Guest Page Cache, Guest Block Layer, /dev/vda, virtio-blk Frontend 를 거쳐 virtqueue 에 도달하는 위에서 아래로 읽는 흐름도.",
|
||||
"long_description": "위에서 아래로 읽는다. 맨 위 Guest Userspace 구역에 PostgreSQL / Keycloak 이 있고 write() 가 게스트 커널로 내려간다. Guest Kernel 구역 안에서 VFS 가 먼저 받고, ext4 / XFS 가 파일을 block 공간에 배치하고, Guest Page Cache 가 그 내용을 dirty page 로 받아 두었다가 writeback 으로 Guest Block Layer 에 내려보낸다. Guest Block Layer 는 그것을 WRITE 나 FLUSH 요청으로 바꿔 /dev/vda 에 걸고, virtio-blk Frontend 가 그 요청을 virtqueue 에 게시한다. virtqueue 아래의 VM Boundary 부터는 QEMU 와 호스트 계층이라 이 그림에서 잘랐다. 완료가 같은 virtqueue 로 되돌아오는 역방향은 SSOT 의 다른 절이 대는 사실이라 이 그림에 넣지 않았고 본문 문단이 맡는다.",
|
||||
"source_context": {
|
||||
"document": "docs/virtualization/final/document.md",
|
||||
"document_sha256": "181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "128. 전체 구조",
|
||||
"line": 5804
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "component-flow",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"rationale": "이 절이 주장하는 것은 요청 하나가 한 방향으로 지나가는 계층의 순서다. sequence 는 참여자마다 생명선을 세우고 메시지를 주고받는 그림인데 이 구간에는 되돌아오는 메시지가 없어 생명선이 전부 빈 세로줄이 된다. two-zone-pipeline 은 구역 안쪽 엣지 라벨을 캔버스 위쪽에 고정해 writeback 과 WRITE / FLUSH 가 제자리를 잃는다. 구역은 groups 로 두고 흐름은 component-flow 로 세운다.",
|
||||
"focus_node": "virtqueue"
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"id": "guest-userspace",
|
||||
"label": "Guest Userspace",
|
||||
"kind": "boundary",
|
||||
"description": "게스트 사용자 공간. 저장장치를 직접 다루지 않는다.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5807,
|
||||
"end_line": 5809
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "guest-kernel",
|
||||
"label": "Guest Kernel",
|
||||
"kind": "boundary",
|
||||
"description": "게스트 커널 공간. VM Boundary 위쪽 계층이 전부 여기 있다.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5815,
|
||||
"end_line": 5833
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "app",
|
||||
"label": "PostgreSQL / Keycloak",
|
||||
"kind": "service",
|
||||
"role": "source",
|
||||
"shape": "box",
|
||||
"group": "guest-userspace",
|
||||
"description": "파일 연산을 요청하는 게스트 프로세스.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5807,
|
||||
"end_line": 5809
|
||||
},
|
||||
{
|
||||
"start_line": 5885,
|
||||
"end_line": 5885
|
||||
},
|
||||
{
|
||||
"start_line": 5811,
|
||||
"end_line": 5813
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"details": [
|
||||
"read / write",
|
||||
"fsync / sync"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "vfs",
|
||||
"label": "VFS",
|
||||
"kind": "service",
|
||||
"role": "service",
|
||||
"shape": "box",
|
||||
"group": "guest-kernel",
|
||||
"description": "열린 파일이 어느 filesystem 구현에 속하는지 보고 연산을 넘기는 공통 계층.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5815,
|
||||
"end_line": 5817
|
||||
},
|
||||
{
|
||||
"start_line": 5905,
|
||||
"end_line": 5905
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "fs",
|
||||
"label": "ext4 / XFS",
|
||||
"kind": "service",
|
||||
"role": "service",
|
||||
"shape": "box",
|
||||
"group": "guest-kernel",
|
||||
"description": "파일과 디렉터리를 block 공간에 배치하는 게스트 filesystem.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5819,
|
||||
"end_line": 5819
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "page-cache",
|
||||
"label": "Guest Page Cache",
|
||||
"kind": "store",
|
||||
"role": "store",
|
||||
"shape": "box",
|
||||
"group": "guest-kernel",
|
||||
"description": "게스트 RAM 에 있는 cache. write() 가 성공해도 데이터는 아직 여기까지만 확정된다.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5821,
|
||||
"end_line": 5821
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "block-layer",
|
||||
"label": "Guest Block Layer",
|
||||
"kind": "service",
|
||||
"role": "service",
|
||||
"shape": "box",
|
||||
"group": "guest-kernel",
|
||||
"description": "파일 세계의 요청을 block device 세계의 요청으로 바꾸는 계층.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5825,
|
||||
"end_line": 5825
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "vda",
|
||||
"label": "/dev/vda",
|
||||
"kind": "device",
|
||||
"role": "service",
|
||||
"shape": "box",
|
||||
"group": "guest-kernel",
|
||||
"description": "게스트 Linux 가 하나의 block device 로 인식하는 이름.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5829,
|
||||
"end_line": 5829
|
||||
},
|
||||
{
|
||||
"start_line": 5879,
|
||||
"end_line": 5879
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "virtio-blk",
|
||||
"label": "virtio-blk Frontend",
|
||||
"kind": "service",
|
||||
"role": "service",
|
||||
"shape": "box",
|
||||
"group": "guest-kernel",
|
||||
"description": "그 가상 block device 를 제어하는 게스트 커널 driver.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5831,
|
||||
"end_line": 5831
|
||||
},
|
||||
{
|
||||
"start_line": 5789,
|
||||
"end_line": 5789
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "virtqueue",
|
||||
"label": "virtqueue",
|
||||
"kind": "queue",
|
||||
"role": "queue",
|
||||
"shape": "box",
|
||||
"emphasis": "primary",
|
||||
"group": "guest-kernel",
|
||||
"description": "요청이 실리는 자리. 바로 아래가 VM Boundary 다.",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5833,
|
||||
"end_line": 5835
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "app-to-vfs",
|
||||
"from": "app",
|
||||
"to": "vfs",
|
||||
"label": "",
|
||||
"kind": "data",
|
||||
"style": "solid",
|
||||
"order": 1,
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5811,
|
||||
"end_line": 5813
|
||||
},
|
||||
{
|
||||
"start_line": 5890,
|
||||
"end_line": 5890
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "vfs-to-fs",
|
||||
"from": "vfs",
|
||||
"to": "fs",
|
||||
"label": "",
|
||||
"kind": "data",
|
||||
"style": "solid",
|
||||
"order": 2,
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5817,
|
||||
"end_line": 5819
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "fs-to-page-cache",
|
||||
"from": "fs",
|
||||
"to": "page-cache",
|
||||
"label": "",
|
||||
"kind": "data",
|
||||
"style": "solid",
|
||||
"order": 3,
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5819,
|
||||
"end_line": 5821
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "page-cache-to-block-layer",
|
||||
"from": "page-cache",
|
||||
"to": "block-layer",
|
||||
"label": "writeback",
|
||||
"kind": "data",
|
||||
"style": "solid",
|
||||
"order": 4,
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5823,
|
||||
"end_line": 5825
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "block-layer-to-vda",
|
||||
"from": "block-layer",
|
||||
"to": "vda",
|
||||
"label": "WRITE / FLUSH",
|
||||
"kind": "data",
|
||||
"style": "solid",
|
||||
"order": 5,
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5827,
|
||||
"end_line": 5829
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "vda-to-virtio-blk",
|
||||
"from": "vda",
|
||||
"to": "virtio-blk",
|
||||
"label": "",
|
||||
"kind": "data",
|
||||
"style": "solid",
|
||||
"order": 6,
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5829,
|
||||
"end_line": 5831
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "virtio-blk-to-virtqueue",
|
||||
"from": "virtio-blk",
|
||||
"to": "virtqueue",
|
||||
"label": "Virtio block request",
|
||||
"kind": "data",
|
||||
"style": "solid",
|
||||
"order": 7,
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5831,
|
||||
"end_line": 5833
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {
|
||||
"rationale": "component-flow 를 고른 이유는 이 절이 답하는 물음이 「write() 가 virtqueue 에 닿기까지 무엇을 어떤 순서로 지나는가」이기 때문이다. Guest Userspace 와 Guest Kernel 은 §128 이 대괄호로 직접 그어 둔 구역이라 groups 로 두었다. 완료가 같은 virtqueue 로 되돌아오는 역방향은 §166 과 §172 가 대는 사실인데 두 절 모두 이 앵커의 준비된 문맥(§127~§129) 밖이라 넣지 않았다 — 그 문맥 안에서 인용할 줄이 없다. VM Boundary 아래의 QEMU·호스트 계층은 같은 §128 안에 있지만 이 기록이 virtqueue 까지만 따라간다고 밝혀 두었고, 그 아래는 다른 기록의 그림이 맡는다. 첫 엣지에 write() 라벨을 달았더니 라벨 상자가 Guest Kernel 구역 이름을 덮어(PNG 로 확인) 라벨을 지우고 그 두 줄을 출발 노드의 details 로 내렸다. virtio-blk Frontend → virtqueue 엣지의 라벨 「Virtio block request」는 이 앵커의 문맥이 화살표만 그려 두어 이름 자체는 §138 이 대는 것이고, 기록 본문도 같은 이름을 쓴다."
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user