--- /tmp/opencode/df2832/orig.c 2026-09-02 00:22:49.535948645 +0000 +++ /tmp/opencode/df2832/witness.c 2026-09-02 00:22:49.543948543 +0000 @@ -100,6 +100,12 @@ SYSCTL_INT(_debug, OID_AUTO, rush_requests, CTLFLAG_RW, &stat_rush_requests, 0, ""); +/* DF2832 witness counters (IN-GUEST ONLY) */ +static int df2832_hits; +static int df2832_starts; +SYSCTL_INT(_debug, OID_AUTO, df2832_hits, CTLFLAG_RD, &df2832_hits, 0, ""); +SYSCTL_INT(_debug, OID_AUTO, df2832_starts, CTLFLAG_RD, &df2832_starts, 0, ""); + LIST_HEAD(synclist, vnode); #define SC_FLAG_EXIT (0x1) /* request syncer exit */ @@ -353,6 +359,7 @@ mp->mnt_syncer_ctx = NULL; lwkt_reltoken(&ctx->sc_token); + kprintf("DF2832: thr_stop FREE ctx=%p mp=%p\n", ctx, mp); hashdestroy(ctx->syncer_workitem_pending, M_DEVBUF, ctx->syncer_mask); kfree(ctx, M_TEMP); } @@ -572,6 +579,27 @@ } /* + * DF2832 witness: park up to ~500ms emulating preemption between the + * mp->mnt_syncer_ctx load and the atomic RMW below. If the mount is torn + * down while parked, mnt_syncer_ctx != local ctx, i.e. on the stock + * kernel the RMW would operate on memory freed by vn_syncer_thr_stop(). + * On HIT we print and REFRAIN from the RMW (pure evidence, no corruption). + */ +#define DF2832_PARK(ctx, fn) do { \ + int _n; \ + for (_n = 0; _n < 500; ++_n) { \ + if (mp->mnt_syncer_ctx != (ctx)) { \ + atomic_add_int(&df2832_hits, 1); \ + kprintf("DF2832: HIT stale ctx=%p in " \ + fn " after %d ms park (mp=%p)\n", \ + (ctx), _n, mp); \ + return; \ + } \ + tsleep(&df2832_hits, 0, "df2832w", 1); \ + } \ +} while (0) + +/* * Force continuous full syncs until stopped. This may be used by * filesystems waiting on dirty data to be flushed to avoid syncer/tsleep * races. @@ -582,6 +610,8 @@ struct syncer_ctx *ctx; if (mp && (ctx = mp->mnt_syncer_ctx) != NULL) { + atomic_add_int(&df2832_starts, 1); + DF2832_PARK(ctx, "trigger_syncer_start"); if (atomic_fetchadd_int(&ctx->syncer_trigger, 2) <= 1) wakeup(ctx); } @@ -607,6 +637,8 @@ if (mp && (ctx = mp->mnt_syncer_ctx) != NULL) { if ((ctx->syncer_trigger & 1) == 0) { + atomic_add_int(&df2832_starts, 1); + DF2832_PARK(ctx, "trigger_syncer"); atomic_set_int(&ctx->syncer_trigger, 1); wakeup(ctx); }