본문으로 건너뛰기

작업 전체 Status 스냅샷 (2026-06-24)

⚠️ 이 06-24 스냅샷은 00_overview.md(06-25 통합)로 대체됨. 시점 고정 보고용으로 보존. (관련 문서 일부 링크는 분석 본문이 docs/notes/로 이동해 깨진 상태 — 최신은 통합 원장 참조.)

시점 고정 스냅샷. task ID별 라이브 상태는 tasks/index.md가 canonical. 이 문서는 완료/진행중/대기 + follow-up 2건을 한 장에 종합한 보고용.

작업의 큰 줄기는 raw_block 백엔드 io_uring/NVMe 성능 최적화(메인)와 FDP PoC 검증(서브). 모두 #3274(io_uring 인프라, 2026-06-11 머지 완료) 위에 쌓이는 후속 작업이다.


✅ 완료 (머지됨)

#3274 — io_uring 인프라 (06-11 머지) · io_uring_post_pr3274 · perf-findings vs #3274 모든 후속 작업의 토대가 되는 PR입니다. raw_block write/read 경로에 io_uring dispatcher를 도입하고(_write_buffers/_read_buffers), fixed-buffer zero-copy 등록, NVMe passthrough(uring_cmd), MDTS 기반 청크 분할까지 포함됩니다. M1(uring 적용)이 여기에 흡수되어 별도 PR 없이 완료됐습니다.

Cleanup — RawBlockCore 중복 조건 정리 · pending_cleanup 도달 불가능하거나 중복된 조건들을 정리한 워밍업 PR로 머지 완료됐습니다.


🔄 진행 중 — PR 열림 (리뷰 단계)

P0 (#3636) — put_many io_uring batched submit · P0 계획·검증 · batch finalize · review fixes put_many가 키마다 개별적으로 write를 던지던 것을 _put_many_batch_io로 묶어 단일 SQ 제출로 바꾼 핵심 성능 PR입니다. 리뷰 반영 과정에서 importorskip 축소, 동일 배치 내 duplicate key parity 처리, partial-completion rollback, 대량 배치의 fairness를 위한 chunk cap 보강을 추가했고 현재도 리뷰 반영 중입니다.

L3 (#3494) — batched_remove 락 N→1 · L3 변경 노트 · 리뷰 cr-2a031316 RustRawBlockBackend.batched_remove가 키마다 락을 잡던 것을 단일 락으로 줄인 PR입니다. 현재 리뷰 중입니다.

L2→fix (#3698) — dispatch 실패 시 ref/put-task 롤백 · PR #3698 정리 · L2 변경 노트 원래 L2(legacy batched_submit_put_task dedup 배치화)로 시작했지만 NVMe regression으로 dedup은 폐기하고, dispatch 스케줄링 실패 시 ref와 _put_tasks를 롤백하지 않던 버그 수정만 남긴 PR입니다. Gemini 리뷰에서 ExceptionBaseException으로 바꾸라는 지적 1건이 있습니다.

Recovery POSIX (#3835) — bringup 병렬 검증, 대규님 PR · NY+DG 총괄 노트 · 통합 합의안 재시작 시 _validate_loaded_entries가 슬롯 헤더를 직렬로 pread하던 병목을 ThreadPoolExecutor(8 reader) 기반으로 병렬화한 대규님 PR입니다. 이 PR이 dispatch 구조 골격을 만들어놔서 NY의 io_uring batched 구현이 그 위에 합류하는 구조입니다.


🔨 진행 중 — 로컬 구현 완료, PR 대기

P0-B — padded O_DIRECT write를 batched_write로 · perf/iouring-batched-padded-write (워크트리, #3636 stacked) · Part B 계획 #3636이 O_DIRECT + padding 케이스에서 batched_write를 못 쓰고 per-entry write_uring 폴백으로 빠지던 문제를 고친 후속 패치입니다. 근본 원인은 Rust batched_writepayload_len 없이 total_len 기준으로 memcpy하면서 유효 범위 바깥을 읽는 OOB read였고, payload_lens optional 인자 추가 + bounce에서 꼬리 명시적 zero-fill로 수정했습니다. Python의 can_batch 게이트는 완전 제거했습니다. 커밋 4개, 테스트 green 상태이며 #3636 머지 후 rebase해서 PR 제출 예정입니다.

io_uring batched recovery — 실 NVMe 6.08× 검증 완료 · perf/iouring-recovery-batched-read (base=DG #3835) · NY+DG 총괄 노트 · V1 구현·검증 · 실 NVMe 가이드 대규님 #3835가 남긴 _validate_loaded_entries_iouring_serial TODO를 채운 구현입니다. batched_read 단일 제출로 N개 헤더를 한 번에 읽고, iouring_queue_depth(256) 단위로 분할해 메모리 상한을 묶었으며, batch 전체 실패 시 per-slot 폴백으로 격리 동작을 복원했습니다. 실 NVMe(524K entries)에서 직렬 대비 6.08× 확인했습니다. uring_cmd 경로는 EINVAL 버그 발견으로 이 PR에서 제거해 별도 future work(F2)로 분리했으며, #3835 머지 후 PR 제출 예정입니다.

현재 체크아웃된 test-iouring-recovery 브랜치(이 테스트 클론)는 DG POSIX 병렬 + NY io_uring batched recovery를 통합 검증하는 자리.

🔬 진행 중 — FDP PoC (서브 트랙)

  • 단계 1(브랜치 audit) 완료 → 공정 재평가(eval redo) Phase 0 진행 중. → PLAN.md · Phase 0 소스 verify
  • 핵심 발견: separated 모드의 host write 감소가 FDP 확정 효과가 아니라 controller counter artifact일 가능성(WAF ratio 3모드 ≈1.0159 동일, replay op 수 동일). harness/generator 무수정, 오케스트레이션·config만으로 진행 결론. → 반복실험 host write 재해석

🧵 Follow-up 작업 2건 (메인 트랙에서 파생)

F1. Write Coalescing (벡터드 writev, Tier 1)

  • 출처: iouring-batch-coalesce-writev-plan.md (06-16)
  • 상태: planned계획만, 미구현
  • 계기: 팀원 지적 — "#3636 batch io는 submit/wait만 1회로 묶었지 디바이스가 받는 커맨드는 여전히 2N개다. append라면 차라리 MDTS까지 채운 큰 IO 한 방이 낫지 않냐."
  • 핵심 근거(분석 완료):
    • 지금 2N 커맨드인 이유 = Rust batched_write가 버퍼 1개당 opcode::Write SQE 1개. Rust에 writev 없음.
    • 결정적 사실: hdr_total == header_bytes한 키의 헤더+페이로드는 슬롯 연속성과 무관하게 디바이스에서 항상 물리적으로 인접 → Tier 1을 append 가정 없이 항상 유효하게 만듦.
  • 스코프(사용자 확정): Tier 1(키 내부 헤더+페이로드 2→1 커맨드)만. Tier 2(키 사이 merge)는 실측이 "커맨드 수가 병목"임을 입증할 때만.
  • 미해결/주의:
    • 공통 의존성 = Rust opcode::Writev(복사 없는 iovec). Python 단독 불가.
    • P0-B와 같은 batched_write 시그니처를 건드림payload_lens(P0-B) + iovec 그룹 (coalescing) 통합 설계 필요. 통합안 후보: batched_writev(offsets, buffer_groups, payload_lens, total_lens).
    • 4-step 계획(측정 스파이크 go/no-go → Rust primitive → Python TDD → 실 NVMe). Step 0 측정 스파이크가 먼저 — #3636 미머지라 그 위 스택 또는 머지 후 진입.

F2. uring_cmd(passthrough) checkpoint read 실패

  • 출처: uring_cmd_recovery_followup.md (06-23, 06-24 보강)
  • 상태: future work — recovery PR에서 분리·제거, 별도 Rust 트랙으로 격상
  • 증상(실 NVMe, 524K entries, /dev/nvme6n1 ↔ /dev/ng6n1):
    • posix/io_uring(block): 정상 indexed=524272 (io_uring 6.08×)
    • io_uring_cmd: indexed=0_load_meta_payload에서 [Errno 22] EINVAL
  • 원인(확정 단서 + 유력 가설):
    • meta header(offset 0, 단일 4KB 페이지) read 성공, meta payload(~75MiB를 2MiB chunk) read에서 EINVAL → device_path(P1) 문제 아님, payload read 자체 실패.
    • 유력 원인: _read_uring_cmd_buffers 버퍼가 비정렬 bytearray인데 use_odirect=false라 non-bounce로 비정렬 ptr을 그대로 DMA addr로 전달 → passthrough multi-page PRP 페이지 정렬 위반 → EINVAL. 단일 페이지인 header는 통과해서 그동안 안 드러남.
  • 수정 방향(Rust 정렬 bounce):
    let needs_align = self.use_odirect || self.use_uring_cmd;
    비정렬 ptr이면 페이지 정렬 AlignedBuf bounce + copy-back. 영향 범위가 recovery만이 아니라 load_many_into 등 모든 uring_cmd read의 multi-page payload → passthrough read 전반 버그, 별도 이슈/Rust PR(CODEOWNER @DongDongJu 영역)으로 격상 필요.
  • 기존 fix 브랜치/PR 분석 완료:
    • PR #3841 (priv/sy/fix/raw-block-uring-cmd-aligned-buffers, a340ab7): 부분 fix, recovery 미해결. padding 경로(len(dst)<total_len) 임시 버퍼만 정렬. recovery _load_meta_payloadbytearray(total_len) 정확 크기라 else 분기(정렬 안 함)로 빠져 EINVAL 잔존.
    • PR #3812 (core/rawblock-load-many-iouring-batch, 3xdevv): 에러처리/배칭만, 정렬 미수정. uring_cmd read를 read_uringbatched_read로 전환 + wait_iouringVec<bool> 비트맵 반환으로 변경. 버퍼는 여전히 비정렬이고 a340ab7 Python 보강도 무력화. EINVAL 잔존(단 크래시 대신 None→indexed=0). 수정 지점 이동: #3812 후 1순위 fix 위치가 lib.rs:2092 batched_read submit 경로(use_odirect || use_uring_cmd 조건)로 이동.
  • 재활성화 절차: Rust 수정·실 NVMe 검증 후 ① dispatch not use_uring_cmd 제거 ② 테스트 _uring_cmd_uses_sequential_uring_cmd_uses_batched_read ③ 벤치 io_uring_cmd 경로 복원. 제거 시점 구현은 git 이력에 보존됨.

⏸️ 대기 / 보류 (착수 가능하나 미착수)

❌ 폐기된 것 (참고)


임박한 액션 (의존 체인)

  1. #3636 머지 → P0-B PR 제출 (rebase --onto dev)
  2. #3835(DG) 머지 → io_uring recovery PR 제출
  3. F2 EINVAL 근본 수정 — Rust batched_read lib.rs:2092에 use_odirect || use_uring_cmd bounce 조건 추가 (@DongDongJu 영역) → recovery 재활성화
  4. F1 coalescing Step 0 측정 스파이크 (go/no-go) — P0-B와 batched_write 시그니처 공동 설계