Stage B: logging policy documented, level-aware log-ring eviction built, LOG-FLUSH deferred again (FABRIC-3.md §XXXII.4)
Policy decided for the kernel-only audit scope: an interactive command's direct response stays on console_println/console_puts; everything else (state transitions, background diagnostics, audit trails) routes through log_message() at the appropriate level, matching capsule_mint.c's verify_mint() precedent. Documented, not code-swept here -- reclassifying individual sites is Stage D's job. LOG-FLUSH deferred again, explicitly: the per-VM log buffer its own doc comment presumes (vm_log_buffer.h) doesn't exist anywhere in the tree -- building it is real feature work needing its own scoped stage. Level-aware eviction built: log_region_append() now reads the oldest ring slot's own level before evicting it, protecting ERROR/WARN records from being pushed out by INFO/DEBUG churn -- drops the incoming low-priority record instead. Found and fixed an adjacent bug while making this change: the prior two-valued return contract would have made a benign "dropped by design" outcome indistinguishable from a genuine write failure to its one caller, which unconditionally set vm->error on any nonzero return. Changed to a three-valued contract (0 success, 1 dropped by design, -1 genuine failure). Three-arch clean qemu acceptance passed. Eviction path itself not live-exercised (needs 128+ LOG-APPEND calls to fill the ring) -- flagged, matching this project's own precedent for that kind of gap. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BWpNjdwPtFLuVLaAq44L9K
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
5c5896fbc1
commit
c05b70c8d6
@@ -77,6 +77,16 @@ static uint32_t log_region_slot_devblock_from_top(uint32_t slot_index) {
|
||||
return LOG_REGION_DEVBLOCK_FROM_TOP_BASE + 1u + (slot_index / LOG_SLOTS_PER_DEVBLOCK);
|
||||
}
|
||||
|
||||
static int log_region_read_slot(uint32_t slot_index, log_slot_t *out) {
|
||||
uint8_t devblock_buf[4096];
|
||||
uint32_t dft = log_region_slot_devblock_from_top(slot_index);
|
||||
uint32_t slot_in_devblock = slot_index % LOG_SLOTS_PER_DEVBLOCK;
|
||||
|
||||
if (blk_meta_zone_read(dft, devblock_buf) != 0) return -1;
|
||||
memcpy(out, devblock_buf + (size_t)slot_in_devblock * LOG_SLOT_SIZE, sizeof(*out));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int log_region_write_slot(uint32_t slot_index, const log_slot_t *slot) {
|
||||
uint8_t devblock_buf[4096];
|
||||
uint32_t dft = log_region_slot_devblock_from_top(slot_index);
|
||||
@@ -117,7 +127,29 @@ int log_region_append(uint8_t level, uint64_t timestamp,
|
||||
total_slots = ctrl.devblocks * LOG_SLOTS_PER_DEVBLOCK;
|
||||
}
|
||||
if (ctrl.record_count >= total_slots) {
|
||||
/* Still full (growth ceiling already reached) -- evict oldest. */
|
||||
/* Still full (growth ceiling already reached) -- evict oldest,
|
||||
* unless doing so would discard higher-priority history for a
|
||||
* lower-priority newcomer (FABRIC-3.md §XXXII.4, 2026-09-15:
|
||||
* plain FIFO eviction here was flagged as level-blind -- a
|
||||
* flood of INFO/DEBUG noise could push out real ERROR/WARN
|
||||
* records). Read the oldest slot's own level before evicting:
|
||||
* if it's ERROR/WARN and the incoming record is not, protect
|
||||
* it -- drop the incoming record instead of evicting real
|
||||
* history. Any other combination (oldest is already low
|
||||
* priority, or the incoming record is itself ERROR/WARN)
|
||||
* evicts exactly as before. A read failure on the oldest slot
|
||||
* (should not happen -- it was written by this same function)
|
||||
* falls back to the prior unconditional-eviction behavior
|
||||
* rather than wedging the ring. */
|
||||
log_slot_t oldest;
|
||||
int oldest_protected = 0;
|
||||
if (log_region_read_slot(ctrl.head_slot, &oldest) == 0) {
|
||||
oldest_protected = (oldest.level <= LOG_REGION_PROTECTED_MAX_LEVEL);
|
||||
}
|
||||
int incoming_protected = (level <= LOG_REGION_PROTECTED_MAX_LEVEL);
|
||||
if (oldest_protected && !incoming_protected) {
|
||||
return 1; /* dropped by design, not a failure -- see header */
|
||||
}
|
||||
ctrl.head_slot = (ctrl.head_slot + 1u) % total_slots;
|
||||
ctrl.record_count--;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user