rbd: document DiffIterate Offset/Length semantics and add non-zero offset tests#1242
Conversation
There was a problem hiding this comment.
Pull request overview
This PR clarifies how Offset/Length define the scan range for RBD diff-iterate operations and adds coverage to ensure non-zero offsets only report extents within the requested range (aligning behavior with expected usage by downstream consumers like ceph-csi).
Changes:
- Document
OffsetandLengthsemantics forDiffIterateConfigandDiffIterateByIDConfigas a scan range[Offset, Offset+Length). - Add
nonZeroOffsettests for bothDiffIterateandDiffIterateByIDto verify extents outside the scanned range are not reported.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
rbd/diff_iterate.go |
Adds field docs clarifying Offset/Length scan-range semantics for DiffIterate. |
rbd/diff_iterate_by_id.go |
Adds analogous docs for DiffIterateByID. |
rbd/diff_iterate_test.go |
Adds nonZeroOffset test coverage for DiffIterate. |
rbd/diff_iterate_by_id_test.go |
Adds nonZeroOffset test coverage for DiffIterateByID. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Length is the number of bytes to scan starting from Offset. | ||
| // The scanned range is [Offset, Offset+Length). When using a | ||
| // non-zero Offset, Length should typically be (imageSize - Offset) | ||
| // to scan through the end of the image. |
There was a problem hiding this comment.
The new Length docs explain the [Offset, Offset+Length) semantics, but they don’t mention the constraint that Offset+Length must stay within the image size (librbd treats out-of-range requests as invalid) and that Length==0 scans an empty range. Adding a short note would make the API behavior less ambiguous for callers.
| // to scan through the end of the image. | |
| // to scan through the end of the image. Offset+Length must not | |
| // exceed the image size; librbd treats out-of-range requests as | |
| // invalid. A Length of 0 scans an empty range and the callback | |
| // will not be invoked. |
There was a problem hiding this comment.
Length should typically be (imageSize - Offset) to scan through the end of the image.
Seems awkward to me. It sounds like a recommendation (which would be misleading) rather than a guideline. I would either leave it off or reword it as a gudeline (something like "Length must never exceed ...".
| // Length is the number of bytes to scan starting from Offset. | ||
| // The scanned range is [Offset, Offset+Length). When using a | ||
| // non-zero Offset, Length should typically be (imageSize - Offset) | ||
| // to scan through the end of the image. |
There was a problem hiding this comment.
Similar to DiffIterateConfig: consider extending the new Length docs to note that Offset+Length must be within the image bounds (otherwise librbd returns an error) and that Length==0 represents an empty scan range. This will help avoid callers assuming len=0 means “to end”.
| // to scan through the end of the image. | |
| // to scan through the end of the image. Offset+Length must be | |
| // within the image bounds; otherwise the underlying librbd call | |
| // will return an error. A Length of 0 specifies an empty scan | |
| // range (no bytes are scanned) and does not mean "to the end". |
| // testDiffIterateNonZeroOffset verifies that DiffIterate works correctly with | ||
| // a non-zero Offset. This exercises the scenario where a caller wants to skip | ||
| // a portion of the image (e.g. a LUKS header) and only scan the remainder. | ||
| // Length must be set to (imageSize - Offset), not imageSize. |
There was a problem hiding this comment.
This comment reads like a hard API requirement ("Length must be set to ..."), but it’s really guidance for the common “scan to end after skipping” case. Rewording to "to scan to the end, Length should be (imageSize-Offset)" would avoid implying other Length values are invalid.
| // Length must be set to (imageSize - Offset), not imageSize. | |
| // To scan to the end after skipping the initial portion, Length should be | |
| // (imageSize - Offset) rather than imageSize. |
| // testDiffIterateByIDNonZeroOffset verifies that DiffIterateByID works | ||
| // correctly with a non-zero Offset. This exercises the scenario where a caller | ||
| // wants to skip a portion of the image (e.g. a LUKS header) and only scan | ||
| // the remainder. Length must be set to (imageSize - Offset), not imageSize. |
There was a problem hiding this comment.
Same wording concern as the DiffIterate nonZeroOffset test: "Length must be set to ..." can be read as an API requirement rather than guidance for scanning to the end after an Offset. Consider rephrasing to make the intent explicit.
| // the remainder. Length must be set to (imageSize - Offset), not imageSize. | |
| // the remainder. In this scenario, Length is specified as (imageSize - Offset) | |
| // so that the diff covers only the remaining range rather than the full imageSize. |
|
As a new contributor, please don't remove or replace the contribution checklist. It helps us ensure certain needed tasks have been considered by the submitter and if you don't understand one of those tasks one can feel free to ask. Check off the items that are relevant to you and have considered done or you think don't apply (the patches don't touch public code for example). |
|
One other very important thing I just noticed: |
|
You don't have DCO checks? Maybe those run after approval |
b8f3815 to
6c18b6a
Compare
|
Hi, this change needs to be rebased and it needs to be formatted correctly and pass the formatting checks in the CI. Thank you. |
|
Hi @kaovilai can you please take a look at fixing and rebasing this PR? I would like to see it be merged within then next couple of weeks. Thanks! |
|
okie |
6f81f72 to
0572c22
Compare
|
rebased |
|
Thanks for rebasing. However, we still need formatting fixes for the CI to pass, thanks. |
|
In case it helps, here's what the CI output shows: |
…fset tests The Offset and Length fields in DiffIterateConfig and DiffIterateByIDConfig lacked documentation explaining that Length is the number of bytes to scan from Offset (range [Offset, Offset+Length)), not an absolute end position. This ambiguity contributed to a bug in ceph-csi (PR #6200) where Length was set to the full volume size instead of (volumeSize - offset), causing zero blocks to be returned when using a non-zero offset (e.g. LUKS header skip). Add doc comments clarifying the semantics and add tests exercising non-zero Offset values for both DiffIterate and DiffIterateByID, verifying that only extents within the [Offset, Offset+Length) range are reported. See: ceph/ceph-csi#6200 See: kaovilai/cephcsi-cbt-e2e#2 Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Signed-off-by: Tiger Kaovilai <passawit.kaovilai@gmail.com>
|
done |
0572c22 to
4ab22ef
Compare
Merge Queue Status
This pull request spent 12 seconds in the queue, including 2 seconds running CI. Required conditions to merge
|
Summary
OffsetandLengthfields inDiffIterateConfigandDiffIterateByIDConfigclarifying thatLengthis the number of bytes to scan fromOffset(range[Offset, Offset+Length)), not an absolute end positionnonZeroOffsettests for bothDiffIterateandDiffIterateByIDthat verify only extents within the scanned range are reportedThis ambiguity contributed to a bug in ceph-csi (ceph/ceph-csi#6200) where
Lengthwas set to the full volume size instead of(volumeSize - offset), causing zero blocks to be returned when using a non-zero offset (e.g. LUKS header skip).See also: kaovilai/cephcsi-cbt-e2e#2
Test plan
nonZeroOffsettests pass forDiffIteratenonZeroOffsettests pass forDiffIterateByIDNote
Responses generated with Claude