Skip to content

Add generic FileRegion support in io_uring stream channel (#16571)#16677

Merged
normanmaurer merged 1 commit into
5.0from
fr5
Apr 22, 2026
Merged

Add generic FileRegion support in io_uring stream channel (#16571)#16677
normanmaurer merged 1 commit into
5.0from
fr5

Conversation

@normanmaurer

Copy link
Copy Markdown
Member

AbstractIoUringStreamChannel only handles DefaultFileRegion (via
splice). Any other FileRegion implementation hits
UnsupportedOperationException from the parent's
filterOutboundMessage.

This is inconsistent with EPOLL and NIO, which accept any FileRegion
via a transferTo fallback. Frameworks like Apache Spark wrap
DefaultFileRegion inside composite FileRegion implementations (e.g.,
MessageWithHeader) that work on NIO and EPOLL but crash on io_uring.

See #16570

For generic FileRegion (non-DefaultFileRegion or when splice is
unsupported), let it pass through filterOutboundMessage into the
outbound buffer, then convert it to a direct ByteBuf in 64 KB
chunks
via FileRegion.transferTo in the write path
(scheduleWriteSingle / writeComplete0).

  • DefaultFileRegion + splice path is unchanged.
  • Data is chunked to limit memory usage — each chunk is read via
    transferTo into a capped ByteBufWritableByteChannel, then submitted
    as an io_uring async send.
  • Partial sends and EAGAIN preserve the chunk buffer for retry;
    unrecoverable errors release it and fail the write.
  • Empty FileRegions (count = 0) submit a 0-byte send so the completion
    path can remove them.

Also enabled testCustomFileRegion in IoUringSocketFileRegionTest and
IoUringBufferRingSocketFileRegionTest.

Any FileRegion implementation is now writable on io_uring, consistent
with EPOLL and NIO.

Transport DefaultFileRegion Generic FileRegion
NIO FileChannel.transferTo region.transferTo
EPOLL native sendfile region.transferTo fallback
io_uring (before) splice UnsupportedOperationException
io_uring (after) splice (unchanged) chunked transferTo → ByteBuf
→ async send

Co-authored-by: Norman Maurer norman_maurer@apple.com

`AbstractIoUringStreamChannel` only handles `DefaultFileRegion` (via
splice). Any other `FileRegion` implementation hits
`UnsupportedOperationException` from the parent's
`filterOutboundMessage`.

This is inconsistent with EPOLL and NIO, which accept any `FileRegion`
via a `transferTo` fallback. Frameworks like Apache Spark wrap
`DefaultFileRegion` inside composite `FileRegion` implementations (e.g.,
`MessageWithHeader`) that work on NIO and EPOLL but crash on io_uring.

See #16570

For generic `FileRegion` (non-`DefaultFileRegion` or when splice is
unsupported), let it pass through `filterOutboundMessage` into the
outbound buffer, then convert it to a direct `ByteBuf` in **64 KB
chunks** via `FileRegion.transferTo` in the write path
(`scheduleWriteSingle` / `writeComplete0`).

- `DefaultFileRegion` + splice path is unchanged.
- Data is chunked to limit memory usage — each chunk is read via
`transferTo` into a capped `ByteBufWritableByteChannel`, then submitted
as an io_uring async send.
- Partial sends and EAGAIN preserve the chunk buffer for retry;
unrecoverable errors release it and fail the write.
- Empty FileRegions (count = 0) submit a 0-byte send so the completion
path can remove them.

Also enabled `testCustomFileRegion` in `IoUringSocketFileRegionTest` and
`IoUringBufferRingSocketFileRegionTest`.

Any `FileRegion` implementation is now writable on io_uring, consistent
with EPOLL and NIO.

| Transport | `DefaultFileRegion` | Generic `FileRegion` |
|---|---|---|
| NIO | `FileChannel.transferTo` | `region.transferTo` |
| EPOLL | native sendfile | `region.transferTo` fallback |
| io_uring (before) | splice | **UnsupportedOperationException** |
| io_uring (after) | splice (unchanged) | chunked `transferTo` → ByteBuf
→ async send |

---------

Co-authored-by: Norman Maurer <norman_maurer@apple.com>
@normanmaurer normanmaurer merged commit abc68df into 5.0 Apr 22, 2026
12 of 13 checks passed
@normanmaurer normanmaurer deleted the fr5 branch April 22, 2026 07:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants