Skip to content

feat(fast_io): refuse SQPOLL when mmap reader is active#4069

Merged
oferchen merged 1 commit into
masterfrom
feat/sqpoll-refuse-on-mmap-2158
May 14, 2026
Merged

feat(fast_io): refuse SQPOLL when mmap reader is active#4069
oferchen merged 1 commit into
masterfrom
feat/sqpoll-refuse-on-mmap-2158

Conversation

@oferchen
Copy link
Copy Markdown
Owner

Summary

  • Adds a defensive configuration-time check on IoUringConfig::build_ring that disables IORING_SETUP_SQPOLL when the caller has signalled an mmap-backed basis reader is live on the same transfer plan. Closes Update Homebrew formula for v3.4.1-rust #2158.
  • Pairing SQPOLL with a file-backed mmap region is a documented kernel hazard: the SQPOLL kthread services SQEs without the user mm context, so cold-page faults on mapped pages bounce through task_work on the original task (deadlock loop on pre-6.x kernels), and concurrent truncation surfaces as in-kernel SIGBUS. See docs/audits/io-uring-sqpoll-mmap-interaction.md plus companion audits mmap-iouring-sqpoll-pagefaults.md and io_uring_sqpoll_mmap_pagefault.md.
  • The new IoUringConfig::mmap_basis_active field defaults to false. When true, build_ring emits a debug_log!(Io, 1, ...) warning, sets the existing SQPOLL_FALLBACK flag, and falls back to a regular ring rather than failing the transfer.
  • Updates docs/audits/io-uring-sqpoll-mmap-interaction.md to mark the S1 caveat resolved with implementation reference.

Why this is defensive, not a bug fix

Today's wired paths already avoid the hazard: DeltaApplicator forces BufferedMap for the basis file when its writer is io_uring-backed, and no preset turns SQPOLL on. The check closes the audit's "OK-with-caveat" gap: a future caller that flips sqpoll = true alongside an MmapStrategy basis is now refused at config time, before any SQE reaches the kernel.

Test plan

  • Unit test: default_config_mmap_basis_inactive confirms the field defaults to false across Default, for_large_files, for_small_files.
  • Unit test: build_ring_sqpoll_with_small_files_no_mmap_keeps_request confirms SQPOLL stays enabled (or falls back for permission reasons) when no mmap basis is active.
  • Unit test: build_ring_sqpoll_with_mmap_basis_disables_sqpoll confirms SQPOLL is refused and sqpoll_fell_back() returns true when mmap_basis_active: true.
  • Unit test: build_ring_no_sqpoll_with_mmap_basis_no_warning confirms the flag is inert when SQPOLL was never requested.
  • CI: fmt+clippy, nextest (stable), Windows, macOS, Linux musl.

Adds a defensive configuration-time check on IoUringConfig::build_ring
that disables SQPOLL when the caller has signalled that an mmap-backed
basis reader is live on the same transfer plan.

Pairing IORING_SETUP_SQPOLL with a file-backed mmap region is a known
kernel hazard: the SQPOLL kthread services SQEs without the user mm
context, so cold-page faults on mapped pages bounce to task_work on the
original task (deadlock loop on pre-6.x kernels) and concurrent
truncation surfaces as in-kernel SIGBUS.

The new mmap_basis_active field on IoUringConfig defaults to false. When
flipped to true, build_ring emits a debug_log warning, sets the existing
SQPOLL_FALLBACK flag, and falls back to a regular ring. Graceful degrade
rather than transfer failure.

Updates docs/audits/io-uring-sqpoll-mmap-interaction.md to mark the S1
caveat resolved with implementation reference.
@github-actions github-actions Bot added the enhancement New feature or request label May 14, 2026
@oferchen oferchen merged commit b778fe8 into master May 14, 2026
45 checks passed
@oferchen oferchen deleted the feat/sqpoll-refuse-on-mmap-2158 branch May 16, 2026 19:50
oferchen added a commit that referenced this pull request May 18, 2026
Adds a defensive configuration-time check on IoUringConfig::build_ring
that disables SQPOLL when the caller has signalled that an mmap-backed
basis reader is live on the same transfer plan.

Pairing IORING_SETUP_SQPOLL with a file-backed mmap region is a known
kernel hazard: the SQPOLL kthread services SQEs without the user mm
context, so cold-page faults on mapped pages bounce to task_work on the
original task (deadlock loop on pre-6.x kernels) and concurrent
truncation surfaces as in-kernel SIGBUS.

The new mmap_basis_active field on IoUringConfig defaults to false. When
flipped to true, build_ring emits a debug_log warning, sets the existing
SQPOLL_FALLBACK flag, and falls back to a regular ring. Graceful degrade
rather than transfer failure.

Updates docs/audits/io-uring-sqpoll-mmap-interaction.md to mark the S1
caveat resolved with implementation reference.
oferchen added a commit that referenced this pull request May 18, 2026
Adds a defensive configuration-time check on IoUringConfig::build_ring
that disables SQPOLL when the caller has signalled that an mmap-backed
basis reader is live on the same transfer plan.

Pairing IORING_SETUP_SQPOLL with a file-backed mmap region is a known
kernel hazard: the SQPOLL kthread services SQEs without the user mm
context, so cold-page faults on mapped pages bounce to task_work on the
original task (deadlock loop on pre-6.x kernels) and concurrent
truncation surfaces as in-kernel SIGBUS.

The new mmap_basis_active field on IoUringConfig defaults to false. When
flipped to true, build_ring emits a debug_log warning, sets the existing
SQPOLL_FALLBACK flag, and falls back to a regular ring. Graceful degrade
rather than transfer failure.

Updates docs/audits/io-uring-sqpoll-mmap-interaction.md to mark the S1
caveat resolved with implementation reference.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant