Find the next populated (data) extent in `[cursor, end)` of `fd`, driven by `lseek(SEEK_DATA)` / `lseek(SEEK_HOLE)`. Returns `Ok(Some((offset, len)))` for the next data extent within the window, or `Ok(None)` if there is no more data. Returns `Err` if the fd or filesystem does not support `SEEK_HOLE` (e.g. hugetlbfs) or for any other I/O error. Callers should treat a first-call error as "fall back
(fd: BorrowedFd<'_>, cursor: u64, end: u64)
| 66 | /// other I/O error. Callers should treat a first-call error as "fall |
| 67 | /// back to the dense path". |
| 68 | fn next_data_extent(fd: BorrowedFd<'_>, cursor: u64, end: u64) -> io::Result<Option<(u64, u64)>> { |
| 69 | let raw = fd.as_raw_fd(); |
| 70 | // SAFETY: BorrowedFd guarantees the fd is valid for the lifetime of |
| 71 | // the borrow; lseek does not consume or close it. |
| 72 | let data_off = unsafe { libc::lseek(raw, cursor as i64, libc::SEEK_DATA) }; |
| 73 | if data_off < 0 { |
| 74 | let e = io::Error::last_os_error(); |
| 75 | // ENXIO from SEEK_DATA means there is no more data at or after |
| 76 | // cursor. Any other error means the filesystem does not support |
| 77 | // SEEK_HOLE; the caller falls back to the dense path. |
| 78 | return if e.raw_os_error() == Some(libc::ENXIO) { |
| 79 | Ok(None) |
| 80 | } else { |
| 81 | Err(e) |
| 82 | }; |
| 83 | } |
| 84 | let data_off = data_off as u64; |
| 85 | if data_off >= end { |
| 86 | return Ok(None); |
| 87 | } |
| 88 | // SAFETY: same as above. |
| 89 | let hole_off = unsafe { libc::lseek(raw, data_off as i64, libc::SEEK_HOLE) }; |
| 90 | if hole_off < 0 { |
| 91 | return Err(io::Error::last_os_error()); |
| 92 | } |
| 93 | let hole_off = (hole_off as u64).min(end); |
| 94 | Ok(Some((data_off, hole_off - data_off))) |
| 95 | } |
| 96 | |
| 97 | struct UffdHandler { |
| 98 | stop_event: EventFd, |