ReadOp.GetOmapValues marshals its startAfter and filterPrefix arguments with C.CString, which truncates Go strings at the first NUL byte before passing them to rados_read_op_omap_get_vals2. Omap keys are arbitrary byte strings, and NUL bytes in them are common in practice: RBD's own pool-level rbd_children object uses keys that are bufferlist encodings of (pool id le64, image id, snap id le64), which virtually always contain NULs.
Any pagination pattern that feeds the last key of one page back as startAfter for the next page silently sends a truncated cursor. The truncated prefix sorts at or before the start of the page just read, so the OSD returns the same page again, more stays true, and the loop never terminates. This affects ReadOp.GetOmapValues directly and everything built on it: IOContext.ListOmapValues, IOContext.GetOmapValues, and IOContext.GetAllOmapValues all iterate infinitely on any omap with ≥ maxReturn entries whose keys contain NULs.
https://github.com/ceph/go-ceph/blob/v0.40.0/rados/read_op.go#L76-L77
https://github.com/ceph/go-ceph/blob/v0.40.0/rados/omap.go#L172
ReadOp.GetOmapValues marshals its startAfter and filterPrefix arguments with C.CString, which truncates Go strings at the first NUL byte before passing them to rados_read_op_omap_get_vals2. Omap keys are arbitrary byte strings, and NUL bytes in them are common in practice: RBD's own pool-level rbd_children object uses keys that are bufferlist encodings of (pool id le64, image id, snap id le64), which virtually always contain NULs.
Any pagination pattern that feeds the last key of one page back as startAfter for the next page silently sends a truncated cursor. The truncated prefix sorts at or before the start of the page just read, so the OSD returns the same page again, more stays true, and the loop never terminates. This affects ReadOp.GetOmapValues directly and everything built on it: IOContext.ListOmapValues, IOContext.GetOmapValues, and IOContext.GetAllOmapValues all iterate infinitely on any omap with ≥ maxReturn entries whose keys contain NULs.
https://github.com/ceph/go-ceph/blob/v0.40.0/rados/read_op.go#L76-L77
https://github.com/ceph/go-ceph/blob/v0.40.0/rados/omap.go#L172