uring_cmd recovery batched — future work
perf/iouring-recovery-batched-read(커밋 87638cb)에서 uring_cmd batched는 제거하고
io_uring(block)+POSIX만 남겼다. uring_cmd recovery 활성화는 아래 선행 버그 수정이 필요하다.
호칭 정정: uring_cmd(passthrough)는 #3274로 dev에 이미 머지됨(
7021790). 따라서 이 버그는 "#3274 영역"이 아니라 현재 dev 코드의 passthrough read 경로(read_uring/_read_uring_cmd_buffers) 문제다.
증상 (실 NVMe, 2026-06-23 · 524,272 entries · /dev/nvme6n1 prepare ↔ /dev/ng6n1 measure)
posix/io_uring(block): 정상 indexed=524272 (io_uring 11.6s, serial 대비 6.08×).io_uring_cmd(char): indexed=0. 로그:_load_meta_payload read failed at offset 4096: [Errno 22] io_uring I/O error_load_meta_payload read failed at offset 134221824: [Errno 22] io_uring I/O errorno valid on-device metadata checkpoint found
원인 (확정 단서 + 유력 가설)
- meta header(offset 0, 4096B=1페이지) read는 성공(magic 읽힘). meta payload(offset
4096+, ~75MiB를
max_data_transfer_size=2MiB chunk로 read)에서 EINVAL. → device_path 검증(P1)이 아니라 payload read 자체 실패. - 유력 원인:
_read_uring_cmd_buffers의 버퍼는 비정렬bytearray인데, uring_cmd는use_odirect=false라read_uring이 non-bounce로 비정렬 ptr을 그대로 NVMe DMA addr로 전달. passthrough는 multi-page 전송 시 PRP 페이지 정렬을 요구 → 2MiB(512페이지) 비정렬 시작이 PRP 위반 → EINVAL. header(단일 페이지=PRP 1개)는 통과해서 그동안 안 드러남. - 정적 코드 분석상 커맨드 구성(
nvme_uring_cmd_prepslba/nlb/opcode/addr/nsid)·NvmeUringCmd레이아웃·lba_shift 출처는 모두 정상.
확정 검증 (다른 PC, 실 NVMe)
- chunk를 4096(단일 페이지)으로 축소 시 EINVAL 사라지면 = multi-page 문제.
- 또는 버퍼를 페이지 정렬 시 사라지면 = 정렬 문제. (둘 다 뿌리는 "정렬 bounce 없음")
수정 방향 (Rust, 정렬 bounce)
- Rust
read_uring/batched_read의 정렬 판정에use_uring_cmd포함 → 비정렬 버퍼를 페이지 정렬AlignedBufbounce로 read + copy-back(기존 bounce 경로 재사용). 정렬 bounce면 2MiB multi-page PRP도 정상 → chunk 축소 불필요.let needs_align = self.use_odirect || self.use_uring_cmd;let ptr_aligned = if needs_align { (ptr as usize).is_multiple_of(align) } else { true };let use_bounce = !ptr_aligned || cap < total_len; - 영향 범위:
load_many_into/_read_buffers등 모든 uring_cmd read의 multi-page payload가 동일 버그. recovery만의 문제 아님 → passthrough read 전반 수정 + 별도 이슈/Rust PR(CODEOWNER @DongDongJu 영역)로 격상.
기존 fix 브랜치 검토 — priv/sy/fix/raw-block-uring-cmd-aligned-buffers (커밋 a340ab7)
결론: 이 브랜치만으로는 recovery 버그 해결 안 됨 (부분 fix).
- 브랜치 내용:
_allocate_aligned_buffer()추가 후,_read_uring_cmd_buffers/_write_uring_cmd_buffers의 padding 경로(len(dst) < total_len)에서 만드는 임시 버퍼만block_align정렬로 교체.# _read_uring_cmd_buffers (core.py:1227~)if len(dst) < total_len: # padding 필요할 때만target = self._allocate_aligned_buffer(total_len) # 정렬 ✅ (fix가 바꾼 곳)copy_back = Trueelse:target = dst[:total_len] # 버퍼 충분하면 호출자 버퍼 그대로 (정렬 안 함 ❌)copy_back = False - recovery는 이 분기를 안 탐:
_load_meta_payload(core.py:1539)가buf = bytearray(total_len)로 정확히 total_len 크기 버퍼를 할당 →len(dst) < total_len이 거짓 →else분기 → 정렬 안 된bytearray를 그대로 DMA 대상으로 전달 → 비정렬 multi-page PRP 위반 → EINVAL 그대로. - 즉 a340ab7은 "호출자 버퍼 < total_len(=padding 필요)" 케이스만 커버. recovery처럼 정확한 크기의 비정렬 버퍼를 직접 넘기는 경로는 미커버.
- → 보강 옵션: (a) Python
else분기도 "ptr 비정렬이면 aligned target bounce + copy_back"으로 확장, 또는 (b) 위 "수정 방향"대로 Rustread_uring에서 비정렬 ptr 무조건 bounce. 호출자별 중복을 피하려면 (b)가 깔끔(모든 호출자 일괄 해결). a340ab7은 (b)와 별개로 padding 경로 정렬을 보장하므로 병행 가치는 있으나 recovery 재활성화의 선행조건은 (b).
재활성화 (Rust 수정·실 NVMe 검증 후)
- core dispatch
_read_slot_headers에서not self.use_uring_cmd제거(1줄) → uring_cmd도_read_slot_headers_batched로. - 테스트
test_validate_loaded_entries_uring_cmd_uses_sequential→_uring_cmd_uses_batched_read. - 벤치
--io-engine io_uring_cmd+--cmd-device-path(measure char) + payloaddevice_pathomit 재도입(block prepare/char measure path 불일치 우회). README io_uring_cmd 블록 복원. - 실 NVMe char device에서
indexed=N확인.
위 1~3의 제거 시점 구현은 git 이력(이 커밋 직전)과 plan
shimmying-squishing-bumblebee.mdF4에 보존됨.