code wiki / (root) / nx_cachewatch_gate.nx

nx_cachewatch_gate.nx source

↩ module page · 229 lines · 12037 B

1// nx_cachewatch_gate.nx -- THE GATE FOR THE WRITE-CACHE AXIS, 2026-09-03. 2// 3// SUBJECT: the BUILT nx_cachewatch elf, forked against fixture /proc trees this gate writes at runtime. 4// It never reads the real /proc, so it is deterministic on any host and cannot pass or fail because of 5// the box it happens to run on -- which matters especially here, since the real host is currently in the 6// RED state and a gate that read it would be indistinguishable from one hardcoded to say RED. 7// 8// T2 IS THE TOOTH THAT CARRIES THE FILE. Fixtures 1 and 2 have BYTE-IDENTICAL cache_info -- both say 9// `mode=WRITE_BACK` -- and differ ONLY in flashcache_progress. If the organ keyed its verdict on `mode` 10// (the obvious field, and the one a reader reaches for first) both would return the same answer and the 11// detector would have read GREEN through the entire outage that motivated it. T2 requires them to 12// DIFFER, so it can only pass on an organ that discriminates on the right field. 13// 14// T3 IS THE POSITIVE CONTROL. T1/T2/T4/T5 all assert a non-GREEN verdict, and a detector hardwired to 15// alarm passes every one. T3 demands a fully healthy tree return GREEN at exit 0. 16// 17// T6 IS THE COUNTER TRAP, AND IT IS THE DEFECT THAT MOTIVATED THE ORGAN. The fixture plants 18// `dirty_writeback_kb=31543788` -- the real live value -- beside `dirty_blocks=0`. A reader that treats 19// the counter as a level reports tens of GB of stranded dirty data on a degraded unmirrored device: an 20// alarming, actionable, WRONG conclusion that this estate's memory recorded once and this organ's author 21// nearly published again. T6 requires the reported level to stay 0 and the counters to be NAMED as 22// refused. 23// 24// Teeth, in order: 25// T1 the live-host condition (cache flushed+disabled, mirror degraded) -> RED, exit 1. 26// T2 DISCRIMINATOR: identical cache_info, progress differs -> AMBER not RED (mode is not the field). 27// T3 POSITIVE CONTROL: a healthy tree -> GREEN, exit 0. 28// T4 an absent flashcache -> UNOBSERVABLE (3), and specifically NOT GREEN. 29// T5 an unreadable progress file -> UNOBSERVABLE, not a cheerful GREEN. 30// T6 COUNTER TRAP: a huge lifetime counter beside dirty_blocks=0 must not become a level. 31// T7 the degraded count reads [2/1] as degraded and leaves [2/2] and [8/8] alone. 32// T8 ANTI-VACUITY: the four verdicts are four DISTINCT exit codes. 33// MEASURED 8/8 GREEN 2026-09-03, bite-proven killed=1 (source 13321 B and deployed subject 23297 B both 34// restored byte-identical). 35// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 36import "nx_syscalls.nx" 37import "nx_gate_verdict.nx" 38import "nx_tool_run.nx" 39 40const CWG_S_A: *u8 = "buildroot/_build/nx_cachewatch.sov.elf" as *u8 41const CWG_S_B: *u8 = "_build/nx_cachewatch.sov.elf" as *u8 42const CWG_S_C: *u8 = "_offc/nx_cachewatch.elf" as *u8 43const CWG_S_D: *u8 = "nx_cachewatch.elf" as *u8 44 45const CWG_ROOT: *u8 = "/tmp/cachewatch" as *u8 46const CWG_PROC: *u8 = "/tmp/cachewatch/proc" as *u8 47const CWG_FCD: *u8 = "/tmp/cachewatch/proc/flashcache" as *u8 48const CWG_INST: *u8 = "/tmp/cachewatch/proc/flashcache/vgtest_cache_1+volume_1" as *u8 49const CWG_CI: *u8 = "/tmp/cachewatch/proc/flashcache/vgtest_cache_1+volume_1/cache_info" as *u8 50const CWG_PG: *u8 = "/tmp/cachewatch/proc/flashcache/vgtest_cache_1+volume_1/flashcache_progress" as *u8 51const CWG_ST: *u8 = "/tmp/cachewatch/proc/flashcache/vgtest_cache_1+volume_1/flashcache_stats" as *u8 52const CWG_MD: *u8 = "/tmp/cachewatch/proc/mdstat" as *u8 53const CWG_ABSENT: *u8 = "/tmp/cachewatch_absent/proc" as *u8 54 55const CWG_CAP: i64 = 16384 56const CWG_MODE: i64 = 420 57const CWG_DIRMODE: i64 = 0x1ff 58 59const CWG_GREEN: i64 = 0 60const CWG_RED: i64 = 1 61const CWG_AMBER: i64 = 2 62const CWG_UNOBS: i64 = 3 63 64// cache_info is BYTE-IDENTICAL for fixtures 1 and 2 -- see T2. 65const CWG_CI_TXT: *u8 = "ssd_dev=/dev/x disk_dev=/dev/y mode=WRITE_BACK total_blocks=15249408 cached_blocks=14501872 dirty_blocks=0 synced_blocks=0 occupied_blocks=670386 \n" 66const CWG_PG_OFF: *u8 = "status=uncacheable_flush_done initial_num_of_dirty=0 remaining_num_of_dirty=0\n" 67const CWG_PG_ON: *u8 = "status=none initial_num_of_dirty=0 remaining_num_of_dirty=0\n" 68const CWG_MD_DEG: *u8 = "md3 : active raid1 nvme1n1p1[1]\n 976757952 blocks super 1.2 [2/1] [_U]\nmd2 : active raid5 a b\n 1 blocks [8/8] [UUUUUUUU]\n" 69const CWG_MD_OK: *u8 = "md3 : active raid1 nvme0n1p1[0] nvme1n1p1[1]\n 976757952 blocks super 1.2 [2/2] [UU]\nmd2 : active raid5 a b\n 1 blocks [8/8] [UUUUUUUU]\n" 70const CWG_STATS: *u8 = "reads=1 writes=2 dirty_writeback_kb=31543788 dirty_write_hits=43493286 write_hits=44269137\n" 71 72func cwg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 73func cwg_write(path: *u8, s: *u8) -> i64 { 74 let n: i64 = cwg_slen(s) 75 let fd: i64 = sys_openat_wr(path, CWG_MODE) 76 if fd < 0 { return 0 - 1 } 77 var off: i64 = 0 78 var go: i64 = 1 79 while go == 1 { 80 if off >= n { go = 0 } else { 81 let w: i64 = sys_write(fd, (s as i64 + off) as *u8, n - off) 82 if w <= 0 { go = 0 } else { off = off + w } 83 } 84 } 85 sys_close(fd) 86 return off 87} 88func cwg_rm(path: *u8) -> i64 { return __syscall(263, 0 - 100, path, 0, 0, 0, 0) } 89func cwg_exists(p: *u8) -> i64 { 90 let fd: i64 = sys_openat_rd(p) 91 if fd < 0 { return 0 } 92 sys_close(fd) 93 return 1 94} 95func cwg_resolve() -> *u8 { 96 if cwg_exists(CWG_S_A) == 1 { return CWG_S_A } 97 if cwg_exists(CWG_S_B) == 1 { return CWG_S_B } 98 if cwg_exists(CWG_S_C) == 1 { return CWG_S_C } 99 if cwg_exists(CWG_S_D) == 1 { return CWG_S_D } 100 return 0 as *u8 101} 102func cwg_find(buf: *u8, n: i64, needle: *u8) -> i64 { 103 let m: i64 = cwg_slen(needle) 104 if m == 0 { return 0 - 1 } 105 var i: i64 = 0 106 var hit: i64 = 0 - 1 107 while i + m <= n { 108 var j: i64 = 0 109 var same: i64 = 1 110 while j < m { 111 if buf[i + j] != needle[j] { same = 0; j = m } else { j = j + 1 } 112 } 113 if same == 1 { if hit < 0 { hit = i + m } } 114 i = i + 1 115 } 116 return hit 117} 118func cwg_run(subj: *u8, verb: *u8, root: *u8, out: *u8, ol: *i64) -> i64 { 119 let av: *i64 = sys_mmap(64) as *i64 120 av[0] = subj as i64 121 av[1] = verb as i64 122 av[2] = root as i64 123 av[3] = 0 124 return tr_run_capture(subj, av, out, CWG_CAP, ol) 125} 126 127func main(argc: i64, argv: *i64) -> i64 { 128 let ctr: *i64 = gv_ctr() 129 gv_head("nx_cachewatch gate -- is the write cache actually caching, and is a lifetime counter ever read as a level" as *u8) 130 131 var subj: *u8 = cwg_resolve() 132 if argc > 1 { subj = argv[1] as *u8 } 133 if subj as i64 == 0 { 134 gv_need("a-built-nx_cachewatch-artifact-on-any-known-path" as *u8, 0, ctr) 135 return gv_verdict("cachewatch" as *u8, ctr, "ABSTAINED: no built subject found, so nothing was measured" as *u8) 136 } 137 gv_puts(" subject resolved by stat: " as *u8); gv_puts(subj); gv_puts("\n" as *u8) 138 139 // fixtures under /tmp/<gate>/ -- never beside a production beat, and built at SETUP because a 140 // teardown does not run when a run crashes. 141 sys_mkdir(CWG_ROOT, CWG_DIRMODE) 142 sys_mkdir(CWG_PROC, CWG_DIRMODE) 143 sys_mkdir(CWG_FCD, CWG_DIRMODE) 144 sys_mkdir(CWG_INST, CWG_DIRMODE) 145 146 let out: *u8 = sys_mmap(CWG_CAP + 16) 147 let ol: *i64 = sys_mmap(16) as *i64 148 149 // ---- T1 the live-host condition ---- 150 cwg_write(CWG_CI, CWG_CI_TXT) 151 cwg_write(CWG_PG, CWG_PG_OFF) 152 cwg_write(CWG_MD, CWG_MD_DEG) 153 let r1: i64 = cwg_run(subj, "check" as *u8, CWG_PROC, out, ol) 154 let n1: i64 = *ol 155 gv_puts(" [T1] cache disabled + mirror degraded -> exit=" as *u8); gv_num(r1) 156 gv_puts(" want=" as *u8); gv_num(CWG_RED); gv_puts("\n" as *u8) 157 var t1: i64 = 0 158 if r1 == CWG_RED { if cwg_find(out, n1, "caching=NO" as *u8) >= 0 { t1 = 1 } } 159 gv_check("the-live-host-condition-cache-flushed-and-disabled-reads-RED" as *u8, t1, ctr) 160 161 // ---- T2 THE DISCRIMINATOR: only flashcache_progress changes ---- 162 cwg_write(CWG_PG, CWG_PG_ON) 163 let r2: i64 = cwg_run(subj, "check" as *u8, CWG_PROC, out, ol) 164 let n2: i64 = *ol 165 gv_puts(" [T2] SAME cache_info (mode=WRITE_BACK both), progress differs -> exit=" as *u8); gv_num(r2) 166 gv_puts(" want=" as *u8); gv_num(CWG_AMBER); gv_puts(" (T1 was " as *u8); gv_num(r1); gv_puts(")\n" as *u8) 167 var t2: i64 = 0 168 if r2 == CWG_AMBER { if r2 != r1 { if cwg_find(out, n2, "caching=YES" as *u8) >= 0 { t2 = 1 } } } 169 gv_check("DISCRIMINATOR-identical-cache_info-yields-a-DIFFERENT-verdict (an organ keyed on mode would answer the same twice and read GREEN through the whole outage)" as *u8, t2, ctr) 170 171 // ---- T3 POSITIVE CONTROL ---- 172 cwg_write(CWG_MD, CWG_MD_OK) 173 let r3: i64 = cwg_run(subj, "check" as *u8, CWG_PROC, out, ol) 174 let n3: i64 = *ol 175 gv_puts(" [T3] fully healthy -> exit=" as *u8); gv_num(r3); gv_puts(" want=0\n" as *u8) 176 var t3: i64 = 0 177 if r3 == CWG_GREEN { if cwg_find(out, n3, "verdict=GREEN" as *u8) >= 0 { t3 = 1 } } 178 gv_check("POSITIVE-CONTROL-a-healthy-tree-reads-GREEN (without this every alarm tooth passes on a detector hardwired to alarm)" as *u8, t3, ctr) 179 180 // ---- T4 absent cache ---- 181 let r4: i64 = cwg_run(subj, "check" as *u8, CWG_ABSENT, out, ol) 182 let n4: i64 = *ol 183 gv_puts(" [T4] no flashcache present -> exit=" as *u8); gv_num(r4); gv_puts(" want=3\n" as *u8) 184 var t4: i64 = 0 185 if r4 == CWG_UNOBS { if r4 != CWG_GREEN { if cwg_find(out, n4, "UNOBSERVABLE" as *u8) >= 0 { t4 = 1 } } } 186 gv_check("an-absent-flashcache-is-UNOBSERVABLE-and-specifically-NOT-GREEN" as *u8, t4, ctr) 187 188 // ---- T5 unreadable progress ---- 189 cwg_rm(CWG_PG) 190 let r5: i64 = cwg_run(subj, "check" as *u8, CWG_PROC, out, ol) 191 gv_puts(" [T5] progress file removed -> exit=" as *u8); gv_num(r5); gv_puts(" want=3\n" as *u8) 192 gv_check("an-unreadable-progress-file-ABSTAINS-rather-than-reporting-a-cheerful-GREEN" as *u8, (r5 == CWG_UNOBS) as i64, ctr) 193 194 // ---- T6 THE COUNTER TRAP ---- 195 cwg_write(CWG_PG, CWG_PG_OFF) 196 cwg_write(CWG_MD, CWG_MD_DEG) 197 cwg_write(CWG_ST, CWG_STATS) 198 let r6: i64 = cwg_run(subj, "explain" as *u8, CWG_PROC, out, ol) 199 let n6: i64 = *ol 200 var t6: i64 = 0 201 if cwg_find(out, n6, "dirty_blocks=0" as *u8) >= 0 { 202 if cwg_find(out, n6, "REFUSED-AS-LEVEL" as *u8) >= 0 { 203 if cwg_find(out, n6, "dirty_writeback_kb" as *u8) >= 0 { t6 = 1 } 204 } 205 } 206 gv_puts(" [T6] stats plant dirty_writeback_kb=31543788 beside dirty_blocks=0 -> level_reported_0=" as *u8) 207 gv_num(t6); gv_puts("\n" as *u8) 208 gv_check("COUNTER-TRAP-a-huge-lifetime-counter-does-NOT-become-a-level-and-both-counters-are-NAMED-as-refused" as *u8, t6, ctr) 209 210 // ---- T7 the degraded count ---- 211 var t7: i64 = 0 212 if cwg_find(out, n6, "degraded_mirrors=1" as *u8) >= 0 { t7 = 1 } 213 gv_puts(" [T7] mdstat carries [2/1] and [8/8] -> degraded counted as 1 = " as *u8); gv_num(t7); gv_puts("\n" as *u8) 214 gv_check("the-degraded-count-reads-2-of-1-as-degraded-and-leaves-a-full-8-of-8-alone" as *u8, t7, ctr) 215 216 // ---- T8 ANTI-VACUITY ---- 217 var t8: i64 = 0 218 if r1 != r2 { if r2 != r3 { if r3 != r4 { if r1 != r3 { if r1 != r4 { if r2 != r4 { t8 = 1 } } } } } } 219 gv_puts(" [T8] four verdicts: " as *u8); gv_num(r1); gv_puts("," as *u8); gv_num(r2) 220 gv_puts("," as *u8); gv_num(r3); gv_puts("," as *u8); gv_num(r4); gv_puts(" all distinct=" as *u8); gv_num(t8); gv_puts("\n" as *u8) 221 gv_check("ANTI-VACUITY-the-four-states-are-four-DISTINCT-exit-codes (a detector returning one constant fails here)" as *u8, t8, ctr) 222 223 gv_kv("red_exit" as *u8, r1) 224 gv_kv("amber_exit" as *u8, r2) 225 gv_kv("green_exit" as *u8, r3) 226 gv_kv("unobservable_exit" as *u8, r4) 227 228 return gv_verdict("cachewatch" as *u8, ctr, "the write-cache axis proven on fixture trees: the disabled-cache condition reads RED, an identical cache_info with a different progress file reads AMBER so mode is provably not the discriminator, a healthy tree reads GREEN, and a lifetime counter is never reported as a level" as *u8) 229}