---
title: "Four Completed Reads Can Return Fewer Bytes Than Four Requested Buffers"
description: "Leviathan Systems — Technical content Published 2026-10-21; updated 2026-10-21."
canonical: "https://www.leviathansystems.co/articles/ai-io-uring-read-completion-returned-byte-count"
last-updated: "2026-10-21"
---

# Four Completed Reads Can Return Fewer Bytes Than Four Requested Buffers

Leviathan Systems — Technical content
Published 2026-10-21; updated 2026-10-21.

For ordinary one-shot io_uring reads, keep each completion result attached to its request and count the positive returned bytes. In READ4, four requests for 4,096 bytes ask for 16,384 bytes. Results of 4,096, 2,048, 0 and -5 (EIO) report 6,144 positive bytes. Four completion reports establish four reported outcomes; they do not establish four full buffers or a complete data-loader batch.

## Read the requested length and completion result separately

The liburing io_uring_prep_read interface describes a read using a file descriptor, destination buffer, requested byte count and offset. Preparing a request for 4,096 bytes expresses the work wanted. The completion queue entry, or CQE, carries the operation's result in its res field.

The read semantics permit a positive result smaller than the request. That short read is successful for the returned length. For a positive-length read of a regular file at its end, zero reports EOF. A negative io_uring result instead carries the negated error code directly; the process's errno variable is not the error return for that completion.

These distinctions matter to a loader: operation completion, successful byte delivery and satisfaction of an input requirement are separate facts. An error can finish an operation and produce a completion report while leaving that input requirement unresolved.

References: [P1](https://man7.org/linux/man-pages/man3/io_uring_prep_read.3.html), [R1](https://man7.org/linux/man-pages/man2/read.2.html), [U1](https://man7.org/linux/man-pages/man7/io_uring.7.html)

## READ4: 16,384 bytes requested, 6,144 positive bytes returned

READ4 is an original hypothetical population of four ordinary one-shot READ requests against stable regular files. Each requests 4,096 bytes into its own distinct buffer. The requests use explicit byte offsets, with no overlapping file ranges, retries, multishot operation or success-completion suppression. Stipulate one CQE per request in this case. The io_uring manual documents modes with different CQE counts, so this premise belongs to READ4 rather than every use of the API.

A reads file A at byte offset 0 and reports 4,096. B reads file A at offset 4,096 and reports 2,048. C reads file B at its expressly stipulated EOF and reports 0. D reads file C at offset 0 and reports the stipulated -5 (EIO). C concerns file B; it supplies no EOF position for file A. B's short result alone does not identify why its read stopped, and D's error supplies no diagnosis of the underlying cause.

Requested bytes total 4 x 4,096 = 16,384. Positive returned bytes total 4,096 + 2,048 = 6,144. The outcome population is two positive reads, one EOF and one error. The -5 identifies an error, not five negative payload bytes to subtract from the successful reads.

References: [P1](https://man7.org/linux/man-pages/man3/io_uring_prep_read.3.html), [R1](https://man7.org/linux/man-pages/man2/read.2.html), [U1](https://man7.org/linux/man-pages/man7/io_uring.7.html)

READ4: requested bytes and reported outcomes
| Request | File and byte offset | Requested bytes | CQE res | Positive bytes reported | Source |
| --- | --- | --- | --- | --- | --- |
| A | File A, 0 | 4,096 | 4,096 | 4,096 | Planning analysis |
| B | File A, 4,096 | 4,096 | 2,048 | 2,048 | Planning analysis |
| C | File B, stipulated EOF | 4,096 | 0 (EOF) | 0 | Planning analysis |
| D | File C, 0 | 4,096 | -5 (EIO) | 0 | Planning analysis |
Invented requests and results, not an observed workload. Zero in the final column means no positive returned-byte count; D remains an error, distinct from C's EOF.

## Bind the result to its request before interpreting the buffer

The io_uring manual explains that requests can complete out of order and describes user_data as a way to associate a completion with its submitted request. The association lets a loader recover the intended file region and destination buffer. Arrival position alone cannot supply that identity.

Suppose READ4's reports arrive C, A, D, B. Assigning the first report to the first submitted request would attach C's EOF to A. The total number of reports could still reach four while the per-buffer interpretation was wrong. Preserving the identities instead leaves the same 6,144-byte total and the correct outcomes for all four requests.

With that binding, A's result covers file A's byte offsets 0 through 4,095, and B's covers offsets 4,096 through 6,143. Their returned prefixes form one contiguous 6,144-byte region of file A, even if B's report arrives first. This arithmetic supplies neither file A's complete length nor any successful data from files B and C.

References: [U1](https://man7.org/linux/man-pages/man7/io_uring.7.html), [P1](https://man7.org/linux/man-pages/man3/io_uring_prep_read.3.html), [R1](https://man7.org/linux/man-pages/man2/read.2.html)

## Carry the valid prefix into the loader's input decision

READ4 provides four destination buffers with a combined requested capacity of 16,384 bytes. That capacity still exists when fewer bytes are read. B's result establishes a 2,048-byte returned prefix in its buffer; its remaining 2,048 positions are outside that successful returned length. Their contents cannot be attributed to this read merely because space was reserved for them.

If the consuming stage requires four complete 4,096-byte chunks, A alone meets the requested-length condition in these results. B supplies a shorter prefix, C supplies EOF, and D supplies an error. Those are different explanations for the missing coverage. Even A's full byte count leaves the meaning and validity of its contents to the application's format requirements.

A loader that expressly permits a shorter final chunk may find B's 2,048 bytes useful. That decision needs the expected file extent and input format; the positive result does not declare itself a valid final chunk. Likewise, C's EOF can be an expected file boundary without proving that the whole dataset has been consumed. The useful output preserves the bytes actually obtained and the questions still open.

References: [R1](https://man7.org/linux/man-pages/man2/read.2.html)

## Compare loader offers by the input they can account for

Consider two fictional loader offers handling exactly READ4. Offer A promises a progress summary of completed requests and reports four. That count is correct within the example. A summary that also labels all four buffers full would go beyond the supplied results.

Offer B promises a per-request return identifying the file region, requested length, actual positive length and outcome. For the same four completions, its summary retains A's 4,096 bytes, B's 2,048-byte prefix, C's EOF and D's error. It reports 6,144 positive bytes and leaves the consumer's batch-readiness decision tied to the expected inputs. These are proposed reporting behaviors, not measured product results.

Choose the reporting scope that reaches the next stage's requirement. A request counter can be sufficient for progress monitoring when another identified layer already accounts for input lengths and exceptions. A buyer purchasing a loader handoff for fixed-size chunks needs that additional accounting included somewhere in the supplied system.

Ask the software provider what a ready batch means for short input, an expected EOF and a failed request, and which component owns that decision. A proposal should explain how its reported input coverage relates to the consumer's declared file ranges or records. Four reported outcomes are useful information; the buyer needs the relationship between those outcomes and the input being purchased.

## Keep the returned-byte account attached to its boundary

READ4's 6,144 bytes describe successful returns into application buffers. The example supplies no elapsed interval, physical-media activity or performance result. Its four CQEs also supply no NVMe queue-resource count.

Once a loader's returned-byte account is understood, the related page-cache article helps evaluate the origin of application read bytes, and the GPUDirect Storage article helps evaluate their memory path. The NVMe queue article addresses command organization. Those guides answer the next storage questions without changing READ4's byte or outcome totals.

## Connect a separate equipment installation project

If the selected loader and storage system also require equipment mounting and external IT cabling, Leviathan's rack-and-stack service provides the relevant physical scope discussion. Use the related service and project-inquiry links with a nonconfidential equipment list, released rack positions and connection requirements, site constraints and required installation records.

This read-result explanation is educational. Loader implementation, storage administration and application acceptance remain with the appointed software and storage specialists. The installation inquiry defines the separate physical work, handoff and availability.

References: [L1](https://www.leviathansystems.co/services/rack-and-stack)

## Primary sources

- [P1 — liburing manual: io_uring_prep_read(3)](https://man7.org/linux/man-pages/man3/io_uring_prep_read.3.html). Checked 2026-10-21. Defines the requested buffer, length and offset, and CQE error encoding for the named read interface.
- [R1 — Linux man-pages 6.19: read(2)](https://man7.org/linux/man-pages/man2/read.2.html). Checked 2026-10-21. Defines returned bytes, successful short reads and regular-file EOF. Application input requirements remain separate.
- [U1 — liburing manual: io_uring(7)](https://man7.org/linux/man-pages/man7/io_uring.7.html). Checked 2026-10-21. Explains CQE results, out-of-order completion, request identity and modes that change the ordinary CQE count.
- [L1 — Leviathan Systems: Rack-and-Stack Installation](https://www.leviathansystems.co/services/rack-and-stack). Checked 2026-10-21. Supports a separate agreed scope for equipment mounting, physical IT cabling, labels and installation records.

## Related Leviathan resources

- [Application read bytes and the storage page-cache boundary](/articles/storage-page-cache-direct-io-measurement-boundary)
- [GPUDirect Storage: direct path and compatible file I/O](/articles/gpudirect-storage-direct-path-versus-compatible-io)
- [NVMe queues and command resources](/articles/nvme-submission-completion-queues-versus-media-parallelism)
- [Rack-and-stack installation for selected equipment](/services/rack-and-stack)
- [Discuss a separate physical installation project](/contact?service=rack-and-stack&from=%2Farticles%2Fai-io-uring-read-completion-returned-byte-count)

## Does the selected equipment need physical installation?

Share a nonconfidential equipment, rack, connection and site outline to discuss the separate installation scope, required handoff and availability.

[Discuss the scope](/contact?service=rack-and-stack&from=/articles/ai-io-uring-read-completion-returned-byte-count)
