Re-read a pinned file from the disk before calling its hash wrong ab3204b9974b
A mismatch drops the file's cached pages (posix_fadvise DONTNEED) and hashes it again; when the disk's copy is right, a warning says the cached copy was bad. earth-1 failed every job on the rust image for three hours through one bad cached page while the file was intact. closes #22
- Author
- Andy McCall @andymccall <[email protected]>
- When
- · 2026-10-02 20:23 UTC
- Signature
- ✔ signed by Andy McCall
- Hash
ab3204b9974bba7d93682a006d2d88fc713dd77052440e87687c16a344ae264c- Depends on
- e0918b887850
- Depended on by
- nothing yet
- In bookmarks
- main newer-pipeline push-uses-login
- In tags
- v0.2.0 v0.3.0 v0.3.1 v0.4.0 v0.5.0 v0.5.1 v0.5.2 v0.5.3
- Edits
- 5 atoms, 0 tree operations, 1 file
Browse the tree at this change
modified crates/flow/src/home.rs +31 −1
| … | 97 unchanged lines |
||
| 98 | 98 | if self.verified.lock().unwrap().get(path) == Some(&stamp) { |
|
| 99 | 99 | return Ok(path.to_path_buf()); |
|
| 100 | 100 | } |
|
| 101 | - | let got = hash_file(path)?; |
|
| 101 | + | let mut got = hash_file(path)?; |
|
| 102 | 102 | if got != blake3_hex { |
|
| 103 | + | // The read may have come from bad cached pages rather than the |
|
| 104 | + | // disk (oxygenflow#22: a RAM fault on Earth failed every job for |
|
| 105 | + | // hours while the file was intact): drop the file's pages and |
|
| 106 | + | // read it again from the disk before giving up. |
|
| 107 | + | drop_cached(path); |
|
| 108 | + | let again = hash_file(path)?; |
|
| 109 | + | if again == blake3_hex { |
|
| 110 | + | eprintln!( |
|
| 111 | + | "warning: {} hashed {got} from the page cache but {again} from the disk: the cached copy was bad (check this machine's memory)", |
|
| 112 | + | path.display() |
|
| 113 | + | ); |
|
| 114 | + | } |
|
| 115 | + | got = again; |
|
| 116 | + | } |
|
| 117 | + | if got != blake3_hex { |
|
| 103 | 118 | bail!("{} has BLAKE3 {got}, but {blake3_hex} is pinned", path.display()); |
|
| 104 | 119 | } |
|
| 105 | 120 | self.verified.lock().unwrap().insert(path.to_path_buf(), stamp); |
|
| 106 | 121 | Ok(path.to_path_buf()) |
|
| 122 | + | } |
|
| 123 | + | } |
|
| 124 | + | ||
| 125 | + | /// Ask the kernel to forget a file's cached pages, so the next read comes |
|
| 126 | + | /// from the disk. Best effort: dirty pages and other platforms stay. |
|
| 127 | + | fn drop_cached(path: &Path) { |
|
| 128 | + | #[cfg(target_os = "linux")] |
|
| 129 | + | if let Ok(f) = std::fs::File::open(path) { |
|
| 130 | + | use std::os::fd::AsRawFd; |
|
| 131 | + | // SAFETY: a valid descriptor; the advice only affects caching. |
|
| 132 | + | unsafe { |
|
| 133 | + | libc::posix_fadvise(f.as_raw_fd(), 0, 0, libc::POSIX_FADV_DONTNEED); |
|
| 134 | + | } |
|
| 107 | 135 | } |
|
| 136 | + | #[cfg(not(target_os = "linux"))] |
|
| 137 | + | let _ = path; |
|
| 108 | 138 | } |
|
| 109 | 139 | ||
| 110 | 140 | pub fn hash_file(path: &Path) -> Result<String> { |
|
| … | 4 unchanged lines |