From 18a0c3cad3cbfb3c82b48689c09ab549ef11a237 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 6 Apr 2023 00:25:03 -0400 Subject: [PATCH 01/28] c3: fixes assert --- pkg/c3/defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/c3/defs.h b/pkg/c3/defs.h index 3a31f67239..7cc8b592fc 100644 --- a/pkg/c3/defs.h +++ b/pkg/c3/defs.h @@ -44,7 +44,7 @@ fprintf(stderr, "\rAssertion '%s' " \ "failed in %s:%d\r\n", \ #x, __FILE__, __LINE__); \ - assert(x); \ + abort(); \ } \ } while(0) #endif From cd7de934bcbbcbbea2d17e2a7b1f4fd3371c485e Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 6 Apr 2023 16:09:57 -0400 Subject: [PATCH 02/28] u3: reformats u3C.wag_w options enum --- pkg/noun/options.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pkg/noun/options.h b/pkg/noun/options.h index 475ad4b1f7..cfe6f492c5 100644 --- a/pkg/noun/options.h +++ b/pkg/noun/options.h @@ -35,15 +35,15 @@ ** _check flags are set inside u3 and heard outside it. */ enum u3o_flag { // execution flags - u3o_debug_ram = 0x1, // debug: gc - u3o_debug_cpu = 0x2, // debug: profile - u3o_check_corrupt = 0x4, // check: gc memory - u3o_check_fatal = 0x8, // check: unrecoverable - u3o_verbose = 0x10, // be remarkably wordy - u3o_dryrun = 0x20, // don't touch checkpoint - u3o_quiet = 0x40, // disable ~& - u3o_hashless = 0x80, // disable hashboard - u3o_trace = 0x100 // enables trace dumping + u3o_debug_ram = 1 << 0, // debug: gc + u3o_debug_cpu = 1 << 1, // debug: profile + u3o_check_corrupt = 1 << 2, // check: gc memory + u3o_check_fatal = 1 << 3, // check: unrecoverable + u3o_verbose = 1 << 4, // be remarkably wordy + u3o_dryrun = 1 << 5, // don't touch checkpoint + u3o_quiet = 1 << 6, // disable ~& + u3o_hashless = 1 << 7, // disable hashboard + u3o_trace = 1 << 8 // enables trace dumping }; /** Globals. From 17a6aacfba1123030f303b4a8ee8ba11d1e9d5e8 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 5 Apr 2023 23:08:27 -0400 Subject: [PATCH 03/28] vere: stubs out new snapshot interface, restricts events.h --- pkg/noun/manage.c | 30 ++++++++++++++++++++++++++++++ pkg/noun/manage.h | 15 +++++++++++++++ pkg/noun/noun.h | 1 - pkg/noun/urth.c | 21 +++++---------------- pkg/vere/benchmarks.c | 4 +--- pkg/vere/main.c | 10 +++++----- pkg/vere/serf.c | 8 ++++---- 7 files changed, 60 insertions(+), 29 deletions(-) diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index 4548052db2..01ab6ff05d 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -1711,6 +1711,34 @@ _cm_limits(void) # endif } +/* u3m_backup(): copy snapshot to .urb/bhk (if it doesn't exist yet). +*/ +c3_o +u3m_backup(c3_o ovw_o) +{ + return u3e_backup(ovw_o); +} + +/* u3m_foul(): dirty all pages and disable tracking. +*/ +void +u3m_foul(void) +{ + if ( c3n == u3e_yolo() ) { + return; + } + + u3e_foul(); +} + +/* u3m_save(): update the checkpoint. +*/ +void +u3m_save(void) +{ + u3e_save(); +} + /* _cm_signals(): set up interrupts, etc. */ static void @@ -1881,6 +1909,8 @@ u3m_boot(c3_c* dir_c, size_t len_i) { c3_o nuu_o; + u3C.dir_c = dir_c; + /* Activate the loom. */ u3m_init(len_i); diff --git a/pkg/noun/manage.h b/pkg/noun/manage.h index 539d45ca7c..dd1a173fc6 100644 --- a/pkg/noun/manage.h +++ b/pkg/noun/manage.h @@ -40,6 +40,21 @@ c3_i u3m_bail(c3_m how_m) __attribute__((noreturn)); + /* u3m_foul(): dirty all pages and disable tracking. + */ + void + u3m_foul(void); + + /* u3m_backup(): copy snapshot to .urb/bhk (if it doesn't exist yet). + */ + c3_o + u3m_backup(c3_o); + + /* u3m_save(): update the checkpoint. + */ + void + u3m_save(void); + /* u3m_init(): start the environment. */ void diff --git a/pkg/noun/noun.h b/pkg/noun/noun.h index 7083cb1a75..d96ba5c721 100644 --- a/pkg/noun/noun.h +++ b/pkg/noun/noun.h @@ -14,7 +14,6 @@ #include "types.h" #include "vortex.h" #include "zave.h" -#include "events.h" #include "imprison.h" #include "log.h" #include "nock.h" diff --git a/pkg/noun/urth.c b/pkg/noun/urth.c index 6c08b742d6..514b317bf1 100644 --- a/pkg/noun/urth.c +++ b/pkg/noun/urth.c @@ -8,7 +8,6 @@ #include #include "allocate.h" -#include "events.h" #include "hashtable.h" #include "imprison.h" #include "jets.h" @@ -374,14 +373,10 @@ _cu_realloc(FILE* fil_u, ur_root_t** tor_u, ur_nvec_t* doc_u) // bypassing page tracking as an optimization // - // NB: u3e_yolo() will mark all as dirty, and + // NB: u3m_foul() will mark all as dirty, and // u3e_save() will reinstate protection flags // - if ( c3n == u3e_yolo() ) { - if ( fil_u ) { - fprintf(fil_u, "uniq: unable to bypass page tracking, continuing\r\n"); - } - } + u3m_foul(); // stash event number // @@ -428,7 +423,7 @@ _cu_realloc(FILE* fil_u, ur_root_t** tor_u, ur_nvec_t* doc_u) // mark all pages dirty // - u3e_foul(); + u3m_foul(); *tor_u = rot_u; *doc_u = cod_u; @@ -841,12 +836,10 @@ u3u_uncram(c3_c* dir_c, c3_d eve_d) // bypassing page tracking as an optimization // - // NB: u3e_yolo() will mark all as dirty, and + // NB: u3m_foul() will mark all as dirty, and // u3e_save() will reinstate protection flags // - if ( c3n == u3e_yolo() ) { - fprintf(stderr, "uncram: unable to bypass page tracking, continuing\r\n"); - } + u3m_foul(); // reinitialize loom // @@ -899,10 +892,6 @@ u3u_uncram(c3_c* dir_c, c3_d eve_d) // u3A->eve_d = eve_d; - // mark all pages dirty - // - u3e_foul(); - // leave rocks on disk // // if ( 0 != c3_unlink(nam_c) ) { diff --git a/pkg/vere/benchmarks.c b/pkg/vere/benchmarks.c index 04c945c822..91f3bc4ab1 100644 --- a/pkg/vere/benchmarks.c +++ b/pkg/vere/benchmarks.c @@ -9,9 +9,7 @@ static void _setup(void) { - u3m_init(1 << 24); - u3m_pave(c3y); - u3e_init(); + u3m_boot_lite(1 << 24); } /* _ames_writ_ex(): |hi packet from fake ~zod to fake ~nec diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 17ae586827..85e6a23c38 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -1577,7 +1577,7 @@ _cw_cram(c3_i argc, c3_c* argv[]) // save even on failure, as we just did all the work of deduplication // - u3e_save(); + u3m_save(); u3_disk_exit(log_u); if ( c3n == ret_o ) { @@ -1660,7 +1660,7 @@ _cw_queu(c3_i argc, c3_c* argv[]) exit(1); } - u3e_save(); + u3m_save(); u3_disk_exit(log_u); fprintf(stderr, "urbit: queu: rock loaded at event %" PRIu64 "\r\n", eve_d); @@ -1728,7 +1728,7 @@ _cw_meld(c3_i argc, c3_c* argv[]) u3u_meld(); u3a_print_memory(stderr, "urbit: meld: gained", (u3a_open(u3R) - pre_w)); - u3e_save(); + u3m_save(); u3_disk_exit(log_u); u3m_stop(); } @@ -1848,7 +1848,7 @@ _cw_pack(c3_i argc, c3_c* argv[]) u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3a_print_memory(stderr, "urbit: pack: gained", u3m_pack()); - u3e_save(); + u3m_save(); u3_disk_exit(log_u); u3m_stop(); } @@ -2022,7 +2022,7 @@ _cw_chop(c3_i argc, c3_c* argv[]) exit(1); } - if ( c3n == u3e_backup(c3y)) { // backup current snapshot + if ( c3n == u3m_backup(c3y)) { // backup current snapshot fprintf(stderr, "chop: error: failed to backup snapshot\r\n"); exit(1); } diff --git a/pkg/vere/serf.c b/pkg/vere/serf.c index 0262d8fcb8..a7dcd13471 100644 --- a/pkg/vere/serf.c +++ b/pkg/vere/serf.c @@ -200,7 +200,7 @@ _serf_grab(u3_noun sac) c3_c* wen_c = u3r_string(wen); c3_c nam_c[2048]; - snprintf(nam_c, 2048, "%s/.urb/put/mass", u3P.dir_c); + snprintf(nam_c, 2048, "%s/.urb/put/mass", u3C.dir_c); struct stat st; if ( -1 == stat(nam_c, &st) ) { @@ -839,7 +839,7 @@ _serf_writ_live_exit(u3_serf* sef_u, c3_w cod_w) c3_c* wen_c = u3r_string(wen); c3_c nam_c[2048]; - snprintf(nam_c, 2048, "%s/.urb/put/profile", u3P.dir_c); + snprintf(nam_c, 2048, "%s/.urb/put/profile", u3C.dir_c); struct stat st; if ( -1 == stat(nam_c, &st) ) { @@ -883,7 +883,7 @@ _serf_writ_live_save(u3_serf* sef_u, c3_d eve_d) exit(1); } - u3e_save(); + u3m_save(); } /* u3_serf_live(): apply %live command [com], producing *ret on c3y. @@ -954,7 +954,7 @@ u3_serf_live(u3_serf* sef_u, u3_noun com, u3_noun* ret) return c3n; } - u3e_save(); + u3m_save(); u3_serf_grab(); *ret = u3nc(c3__live, u3_nul); From 5a9dbab35da5a410e0694d9199627e89afef2277 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 5 Apr 2023 23:41:47 -0400 Subject: [PATCH 04/28] u3: misc cleanup of snapshot system corrects comments removes dead code makes page and offset calculations more consistent --- pkg/noun/events.c | 213 ++++++++++++++++++++-------------------------- 1 file changed, 92 insertions(+), 121 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 0286580501..dfab28ccd2 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -58,7 +58,7 @@ //! - update atomicity is suspect: patch application must either //! completely succeed or leave on-disk segments intact. unapplied //! patches can be discarded (triggering event replay), but once -//! patch application begins it must succeed (can fail if disk is full). +//! patch application begins it must succeed. //! may require integration into the overall signal-handling regime. //! - any errors are handled with assertions; failed/partial writes are not //! retried. @@ -67,7 +67,6 @@ //! //! - use platform specific page fault mechanism (mach rpc, userfaultfd, &c). //! - implement demand paging / heuristic page-out. -//! - add a guard page in the middle of the loom to reactively handle stack overflow. //! - parallelism //! @@ -83,18 +82,18 @@ #include "retrieve.h" #include "types.h" +/* _ce_pag_w: word position of given page +** _ce_pag_y: byte position of given page +*/ +#define _ce_pag_w(i) ((size_t)(i) << u3a_page) +#define _ce_pag_y(i) ((size_t)(i) << (u3a_page + 2)) + /// Snapshotting system. u3e_pool u3e_Pool; // Base loom offset of the guard page. static u3p(c3_w) gar_pag_p; -//! Urbit page size in 4-byte words. -static const size_t pag_wiz_i = 1 << u3a_page; - -//! Urbit page size in bytes. -static const size_t pag_siz_i = sizeof(c3_w) * pag_wiz_i; - #ifdef U3_SNAPSHOT_VALIDATION /* Image check. */ @@ -109,8 +108,8 @@ struct { static c3_w _ce_check_page(c3_w pag_w) { - c3_w* mem_w = u3_Loom + (pag_w << u3a_page); - c3_w mug_w = u3r_mug_words(mem_w, (1 << u3a_page)); + c3_w* mem_w = u3_Loom + _ce_pag_w(pag_w); + c3_w mug_w = u3r_mug_words(mem_w, _ce_pag_w(1)); return mug_w; } @@ -128,8 +127,8 @@ u3e_check(c3_c* cap_c) u3m_water(&nwr_w, &swu_w); - nor_w = (nwr_w + ((1 << u3a_page) - 1)) >> u3a_page; - sou_w = (swu_w + ((1 << u3a_page) - 1)) >> u3a_page; + nor_w = (nwr_w + (_ce_pag_w(1) - 1)) >> u3a_page; + sou_w = (swu_w + (_ce_pag_w(1) - 1)) >> u3a_page; } /* Count dirty pages. @@ -155,45 +154,6 @@ u3e_check(c3_c* cap_c) u3l_log("%s: sum %x (%x, %x)", cap_c, sum_w, nor_w, sou_w); } } - -/* _ce_maplloc(): crude off-loom allocator. -*/ -static void* -_ce_maplloc(c3_w len_w) -{ - void* map_v; - - map_v = mmap(0, - len_w, - (PROT_READ | PROT_WRITE), - (MAP_ANON | MAP_PRIVATE), - -1, 0); - - if ( -1 == (c3_ps)map_v ) { - c3_assert(0); - } - else { - c3_w* map_w = map_v; - - map_w[0] = len_w; - - return map_w + 1; - } -} - -/* _ce_mapfree(): crude off-loom allocator. -*/ -static void -_ce_mapfree(void* map_v) -{ - c3_w* map_w = map_v; - c3_i res_i; - - map_w -= 1; - res_i = munmap(map_w, map_w[0]); - - c3_assert(0 == res_i); -} #endif #ifdef U3_GUARD_PAGE @@ -209,22 +169,22 @@ _ce_center_guard_page(void) bot_p = u3a_outa(u3_Loom); } else if ( c3y == u3a_is_north(u3R) ) { - top_p = c3_rod(u3R->cap_p, pag_wiz_i); - bot_p = c3_rop(u3R->hat_p, pag_wiz_i); + top_p = c3_rod(u3R->cap_p, _ce_pag_w(1)); + bot_p = c3_rop(u3R->hat_p, _ce_pag_w(1)); } else { - top_p = c3_rod(u3R->hat_p, pag_wiz_i); - bot_p = c3_rop(u3R->cap_p, pag_wiz_i); + top_p = c3_rod(u3R->hat_p, _ce_pag_w(1)); + bot_p = c3_rop(u3R->cap_p, _ce_pag_w(1)); } - if ( top_p < bot_p + pag_wiz_i ) { + if ( top_p < bot_p + _ce_pag_w(1) ) { fprintf(stderr, "loom: not enough memory to recenter the guard page\r\n"); goto bail; } const u3p(c3_w) old_gar_p = gar_pag_p; const c3_w mid_p = (top_p - bot_p) / 2; - gar_pag_p = bot_p + c3_rod(mid_p, pag_wiz_i); + gar_pag_p = bot_p + c3_rod(mid_p, _ce_pag_w(1)); if ( old_gar_p == gar_pag_p ) { fprintf(stderr, "loom: can't move the guard page to the same location" @@ -233,7 +193,7 @@ _ce_center_guard_page(void) goto bail; } - if ( -1 == mprotect(u3a_into(gar_pag_p), pag_siz_i, PROT_NONE) ) { + if ( -1 == mprotect(u3a_into(gar_pag_p), _ce_pag_y(1), PROT_NONE) ) { fprintf(stderr, "loom: failed to protect the guard page " "(base address %p): %s\r\n", @@ -280,7 +240,7 @@ u3e_fault(void* adr_v, c3_i ser_i) #ifdef U3_GUARD_PAGE // The fault happened in the guard page. - if ( gar_pag_p <= adr_p && adr_p < gar_pag_p + pag_wiz_i ) { + if ( gar_pag_p <= adr_p && adr_p < gar_pag_p + _ce_pag_w(1) ) { if ( 0 == _ce_center_guard_page() ) { return 0; } @@ -295,8 +255,8 @@ u3e_fault(void* adr_v, c3_i ser_i) u3P.dit_w[blk_w] |= (1 << bit_w); - if ( -1 == mprotect((void *)(u3_Loom + (pag_w << u3a_page)), - pag_siz_i, + if ( -1 == mprotect((void *)(u3_Loom + _ce_pag_w(pag_w)), + _ce_pag_y(1), (PROT_READ | PROT_WRITE)) ) { fprintf(stderr, "loom: fault mprotect: %s\r\n", strerror(errno)); @@ -338,20 +298,19 @@ _ce_image_open(u3e_image* img_u) return c3n; } else { - c3_d siz_d = buf_u.st_size; - c3_d pgs_d = (siz_d + (c3_d)(pag_siz_i - 1)) >> - (c3_d)(u3a_page + 2); + c3_z siz_z = buf_u.st_size; + c3_z pgs_z = (siz_z + (_ce_pag_y(1) - 1)) >> (u3a_page + 2); - if ( !siz_d ) { + if ( !siz_z ) { return c3y; } else { - if ( siz_d != (pgs_d << (c3_d)(u3a_page + 2)) ) { - fprintf(stderr, "%s: corrupt size %" PRIx64 "\r\n", ful_c, siz_d); + if ( siz_z != _ce_pag_y(pgs_z) ) { + fprintf(stderr, "%s: corrupt size %zu\r\n", ful_c, siz_z); return c3n; } - img_u->pgs_w = (c3_w) pgs_d; - c3_assert(pgs_d == (c3_d)img_u->pgs_w); + img_u->pgs_w = (c3_w)pgs_z; + c3_assert( pgs_z == (c3_z)img_u->pgs_w ); return c3y; } @@ -461,7 +420,7 @@ static c3_o _ce_patch_verify(u3_ce_patch* pat_u) { c3_w pag_w, mug_w; - c3_w mem_w[pag_wiz_i]; + c3_w mem_w[_ce_pag_w(1)]; c3_zs ret_zs; if ( U3E_VERLAT != pat_u->con_u->ver_w ) { @@ -475,25 +434,26 @@ _ce_patch_verify(u3_ce_patch* pat_u) pag_w = pat_u->con_u->mem_u[i_z].pag_w; mug_w = pat_u->con_u->mem_u[i_z].mug_w; - if ( -1 == lseek(pat_u->mem_i, (i_z << (u3a_page + 2)), SEEK_SET) ) { + if ( -1 == lseek(pat_u->mem_i, _ce_pag_y(i_z), SEEK_SET) ) { fprintf(stderr, "loom: patch seek: %s\r\n", strerror(errno)); return c3n; } - if ( pag_siz_i != (ret_zs = read(pat_u->mem_i, mem_w, pag_siz_i)) ) { + if ( _ce_pag_y(1) != (ret_zs = read(pat_u->mem_i, mem_w, _ce_pag_y(1))) ) { if ( 0 < ret_zs ) { fprintf(stderr, "loom: patch partial read: %"PRIc3_zs"\r\n", ret_zs); } else { - fprintf(stderr, "loom: patch read: fail %"PRIc3_zs" of %"PRIc3_z" bytes\r\n", - ret_zs, pag_siz_i); + fprintf(stderr, "loom: patch read: fail %s\r\n", strerror(errno)); } return c3n; } + { - c3_w nug_w = u3r_mug_words(mem_w, pag_wiz_i); + c3_w nug_w = u3r_mug_words(mem_w, _ce_pag_w(1)); if ( mug_w != nug_w ) { - fprintf(stderr, "loom: patch mug mismatch %"PRIc3_w"/%"PRIc3_z"; (%"PRIxc3_w", %"PRIxc3_w")\r\n", + fprintf(stderr, "loom: patch mug mismatch" + " %"PRIc3_w"/%"PRIc3_z"; (%"PRIxc3_w", %"PRIxc3_w")\r\n", pag_w, i_z, mug_w, nug_w); return c3n; } @@ -575,12 +535,12 @@ _ce_patch_write_page(u3_ce_patch* pat_u, { ssize_t ret_i; - if ( -1 == lseek(pat_u->mem_i, pgc_w * pag_siz_i, SEEK_SET) ) { + if ( -1 == lseek(pat_u->mem_i, _ce_pag_y(pgc_w), SEEK_SET) ) { fprintf(stderr, "loom: patch page seek: %s\r\n", strerror(errno)); c3_assert(0); } - if ( pag_siz_i != (ret_i = write(pat_u->mem_i, mem_w, pag_siz_i)) ) { + if ( _ce_pag_y(1) != (ret_i = write(pat_u->mem_i, mem_w, _ce_pag_y(1))) ) { if ( 0 < ret_i ) { fprintf(stderr, "loom: patch page partial write: %zu\r\n", (size_t)ret_i); @@ -618,18 +578,18 @@ _ce_patch_save_page(u3_ce_patch* pat_u, c3_w bit_w = (pag_w & 31); if ( u3P.dit_w[blk_w] & (1 << bit_w) ) { - c3_w* mem_w = u3_Loom + (pag_w << u3a_page); + c3_w* mem_w = u3_Loom + _ce_pag_w(pag_w); pat_u->con_u->mem_u[pgc_w].pag_w = pag_w; - pat_u->con_u->mem_u[pgc_w].mug_w = u3r_mug_words(mem_w, pag_wiz_i); + pat_u->con_u->mem_u[pgc_w].mug_w = u3r_mug_words(mem_w, _ce_pag_w(1)); #if 0 u3l_log("protect a: page %d", pag_w); #endif _ce_patch_write_page(pat_u, pgc_w, mem_w); - if ( -1 == mprotect(u3_Loom + (pag_w << u3a_page), - pag_siz_i, + if ( -1 == mprotect(u3_Loom + _ce_pag_w(pag_w), + _ce_pag_y(1), PROT_READ) ) { fprintf(stderr, "loom: patch mprotect: %s\r\n", strerror(errno)); @@ -658,8 +618,8 @@ _ce_patch_compose(void) u3m_water(&nwr_w, &swu_w); - nor_w = (nwr_w + (pag_wiz_i - 1)) >> u3a_page; - sou_w = (swu_w + (pag_wiz_i - 1)) >> u3a_page; + nor_w = (nwr_w + (_ce_pag_w(1) - 1)) >> u3a_page; + sou_w = (swu_w + (_ce_pag_w(1) - 1)) >> u3a_page; c3_assert( ((gar_pag_p >> u3a_page) >= nor_w) && ((gar_pag_p >> u3a_page) <= (u3a_pages - (sou_w + 1))) ); @@ -736,8 +696,7 @@ _ce_image_sync(u3e_image* img_u) { if ( -1 == c3_sync(img_u->fid_i) ) { fprintf(stderr, "loom: image (%s) sync failed: %s\r\n", - img_u->nam_c, - strerror(errno)); + img_u->nam_c, strerror(errno)); c3_assert(!"loom: image sync"); } } @@ -747,11 +706,20 @@ _ce_image_sync(u3e_image* img_u) static void _ce_image_resize(u3e_image* img_u, c3_w pgs_w) { + c3_z off_z = _ce_pag_y(pgs_w); + off_t off_i = (off_t)off_z; + if ( img_u->pgs_w > pgs_w ) { - if ( ftruncate(img_u->fid_i, pgs_w << (u3a_page + 2)) ) { + if ( off_z != (size_t)off_i ) { + fprintf(stderr, "loom: image (%s) truncate: " + "offset overflow (%" PRId64 ") for page %u\r\n", + img_u->nam_c, (c3_ds)off_i, pgs_w); + c3_assert(0); + } + + if ( ftruncate(img_u->fid_i, off_i) ) { fprintf(stderr, "loom: image (%s) truncate: %s\r\n", - img_u->nam_c, - strerror(errno)); + img_u->nam_c, strerror(errno)); c3_assert(0); } } @@ -786,7 +754,7 @@ _ce_patch_apply(u3_ce_patch* pat_u) // for ( i_w = 0; i_w < pat_u->con_u->pgs_w; i_w++ ) { c3_w pag_w = pat_u->con_u->mem_u[i_w].pag_w; - c3_w mem_w[pag_wiz_i]; + c3_w mem_w[_ce_pag_w(1)]; c3_i fid_i; c3_z off_w; @@ -799,7 +767,7 @@ _ce_patch_apply(u3_ce_patch* pat_u) off_w = (u3P.pag_w - (pag_w + 1)); } - if ( pag_siz_i != (ret_i = read(pat_u->mem_i, mem_w, pag_siz_i)) ) { + if ( _ce_pag_y(1) != (ret_i = read(pat_u->mem_i, mem_w, _ce_pag_y(1))) ) { if ( 0 < ret_i ) { fprintf(stderr, "loom: patch apply partial read: %zu\r\n", (size_t)ret_i); @@ -810,11 +778,11 @@ _ce_patch_apply(u3_ce_patch* pat_u) c3_assert(0); } else { - if ( -1 == lseek(fid_i, (off_w << (u3a_page + 2)), SEEK_SET) ) { + if ( -1 == lseek(fid_i, _ce_pag_y(off_w), SEEK_SET) ) { fprintf(stderr, "loom: patch apply seek: %s\r\n", strerror(errno)); c3_assert(0); } - if ( pag_siz_i != (ret_i = write(fid_i, mem_w, pag_siz_i)) ) { + if ( _ce_pag_y(1) != (ret_i = write(fid_i, mem_w, _ce_pag_y(1))) ) { if ( 0 < ret_i ) { fprintf(stderr, "loom: patch apply partial write: %zu\r\n", (size_t)ret_i); @@ -826,7 +794,7 @@ _ce_patch_apply(u3_ce_patch* pat_u) } } #if 0 - u3l_log("apply: %d, %x", pag_w, u3r_mug_words(mem_w, pag_wiz_i)); + u3l_log("apply: %d, %x", pag_w, u3r_mug_words(mem_w, _ce_pag_w(1))); #endif } } @@ -844,7 +812,7 @@ _ce_image_blit(u3e_image* img_u, ssize_t ret_i; c3_w i_w; - c3_w siz_w = pag_siz_i; + c3_w siz_w = _ce_pag_y(1); if ( -1 == lseek(img_u->fid_i, 0, SEEK_SET) ) { fprintf(stderr, "loom: image (%s) blit seek 0: %s\r\n", @@ -884,12 +852,12 @@ _ce_image_blit(u3e_image* img_u, */ static void _ce_image_fine(u3e_image* img_u, - c3_w* ptr_w, - c3_ws stp_ws) + c3_w* ptr_w, + c3_ws stp_ws) { ssize_t ret_i; c3_w i_w; - c3_w buf_w[pag_wiz_i]; + c3_w buf_w[_ce_pag_w(1)]; if ( -1 == lseek(img_u->fid_i, 0, SEEK_SET) ) { fprintf(stderr, "loom: image fine seek 0: %s\r\n", strerror(errno)); @@ -899,7 +867,7 @@ _ce_image_fine(u3e_image* img_u, for ( i_w=0; i_w < img_u->pgs_w; i_w++ ) { c3_w mem_w, fil_w; - if ( pag_siz_i != (ret_i = read(img_u->fid_i, buf_w, pag_siz_i)) ) { + if ( _ce_pag_y(1) != (ret_i = read(img_u->fid_i, buf_w, _ce_pag_y(1))) ) { if ( 0 < ret_i ) { fprintf(stderr, "loom: image (%s) fine partial read: %zu\r\n", img_u->nam_c, (size_t)ret_i); @@ -910,8 +878,8 @@ _ce_image_fine(u3e_image* img_u, } c3_assert(0); } - mem_w = u3r_mug_words(ptr_w, pag_wiz_i); - fil_w = u3r_mug_words(buf_w, pag_wiz_i); + mem_w = u3r_mug_words(ptr_w, _ce_pag_w(1)); + fil_w = u3r_mug_words(buf_w, _ce_pag_w(1)); if ( mem_w != fil_w ) { c3_w pag_w = (ptr_w - u3_Loom) >> u3a_page; @@ -930,7 +898,7 @@ _ce_image_fine(u3e_image* img_u, } #endif -/* _ce_image_copy(): +/* _ce_image_copy(): copy all of [fom_u] to [tou_u] */ static c3_o _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) @@ -956,10 +924,10 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) // copy pages into destination image // for ( i_w = 0; i_w < fom_u->pgs_w; i_w++ ) { - c3_w mem_w[pag_wiz_i]; + c3_w mem_w[_ce_pag_w(1)]; c3_w off_w = i_w; - if ( pag_siz_i != (ret_i = read(fom_u->fid_i, mem_w, pag_siz_i)) ) { + if ( _ce_pag_y(1) != (ret_i = read(fom_u->fid_i, mem_w, _ce_pag_y(1))) ) { if ( 0 < ret_i ) { fprintf(stderr, "loom: image (%s) copy partial read: %zu\r\n", fom_u->nam_c, (size_t)ret_i); @@ -971,12 +939,12 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) return c3n; } else { - if ( -1 == lseek(tou_u->fid_i, (off_w << (u3a_page + 2)), SEEK_SET) ) { + if ( -1 == lseek(tou_u->fid_i, _ce_pag_y(off_w), SEEK_SET) ) { fprintf(stderr, "loom: image (%s) copy seek: %s\r\n", tou_u->nam_c, strerror(errno)); return c3n; } - if ( pag_siz_i != (ret_i = write(tou_u->fid_i, mem_w, pag_siz_i)) ) { + if ( _ce_pag_y(1) != (ret_i = write(tou_u->fid_i, mem_w, _ce_pag_y(1))) ) { if ( 0 < ret_i ) { fprintf(stderr, "loom: image (%s) copy partial write: %zu\r\n", tou_u->nam_c, (size_t)ret_i); @@ -993,14 +961,14 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) return c3y; } -/* u3e_backup(); +/* u3e_backup(): copy snapshot to .urb/bhk (if it doesn't exist yet). */ c3_o u3e_backup(c3_o ovw_o) { u3e_image nop_u = { .nam_c = "north", .pgs_w = 0 }; u3e_image sop_u = { .nam_c = "south", .pgs_w = 0 }; - c3_i mod_i = O_RDWR | O_CREAT; + c3_i mod_i = O_RDWR | O_CREAT; // XX O_TRUNC ? c3_c ful_c[8193]; snprintf(ful_c, 8192, "%s/.urb/bhk", u3P.dir_c); @@ -1095,11 +1063,11 @@ u3e_save(void) { _ce_image_fine(&u3P.nor_u, u3_Loom, - pag_wiz_i); + _ce_pag_w(1)); _ce_image_fine(&u3P.sou_u, - (u3_Loom + u3C.wor_i) - pag_wiz_i, - -(ssize_t)pag_wiz_i); + (u3_Loom + u3C.wor_i) - _ce_pag_w(1), + -(ssize_t)_ce_pag_w(1)); c3_assert(u3P.nor_u.pgs_w == u3K.nor_w); c3_assert(u3P.sou_u.pgs_w == u3K.sou_w); @@ -1124,7 +1092,7 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) { size_t sys_i = sysconf(_SC_PAGESIZE); - if ( pag_siz_i % sys_i ) { + if ( _ce_pag_y(1) % sys_i ) { fprintf(stderr, "loom: incompatible system page size (%zuKB)\r\n", sys_i >> 10); exit(1); @@ -1154,6 +1122,7 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) } else { u3_ce_patch* pat_u; + c3_w nor_w, sou_w; /* Load any patch files; apply them to images. */ @@ -1165,9 +1134,12 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) _ce_patch_delete(); } + nor_w = u3P.nor_u.pgs_w; + sou_w = u3P.sou_u.pgs_w; + // detect snapshots from a larger loom // - if ( (u3P.nor_u.pgs_w + u3P.sou_u.pgs_w + 1) >= u3a_pages ) { + if ( (nor_w + sou_w + 1) >= u3P.pag_w ) { fprintf(stderr, "boot: snapshot too big for loom\r\n"); exit(1); } @@ -1181,24 +1153,23 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) { _ce_image_blit(&u3P.nor_u, u3_Loom, - pag_wiz_i); + _ce_pag_w(1)); _ce_image_blit(&u3P.sou_u, - (u3_Loom + u3C.wor_i) - pag_wiz_i, - -(ssize_t)pag_wiz_i); + (u3_Loom + u3C.wor_i) - _ce_pag_w(1), + -(ssize_t)_ce_pag_w(1)); u3l_log("boot: protected loom"); } /* If the images were empty, we are logically booting. */ - if ( (0 == u3P.nor_u.pgs_w) && (0 == u3P.sou_u.pgs_w) ) { + if ( !nor_w && !sou_w ) { u3l_log("live: logical boot"); nuu_o = c3y; } else { - u3a_print_memory(stderr, "live: loaded", - (u3P.nor_u.pgs_w + u3P.sou_u.pgs_w) << u3a_page); + u3a_print_memory(stderr, "live: loaded", _ce_pag_w(nor_w + sou_w)); } } } @@ -1223,7 +1194,7 @@ u3e_yolo(void) return c3n; } - if ( 0 != mprotect(u3a_into(gar_pag_p), pag_siz_i, PROT_NONE) ) { + if ( 0 != mprotect(u3a_into(gar_pag_p), _ce_pag_y(1), PROT_NONE) ) { fprintf(stderr, "loom: failed to protect guard page: %s\r\n", strerror(errno)); c3_assert(0); @@ -1264,7 +1235,7 @@ u3e_ward(u3_post low_p, u3_post hig_p) _ce_center_guard_page(); if ( 0 != mprotect(u3a_into(gar_p), - pag_siz_i, + _ce_pag_y(1), (PROT_READ | PROT_WRITE)) ) { fprintf(stderr, "loom: failed to unprotect old guard page: %s\r\n", From 935df40cf97d3b5871140b50a78587fa7ea33676 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 6 Apr 2023 00:38:24 -0400 Subject: [PATCH 05/28] u3: use pread/pwrite() with snapshot patches --- pkg/noun/events.c | 67 ++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index dfab28ccd2..05a18ad77c 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -434,11 +434,9 @@ _ce_patch_verify(u3_ce_patch* pat_u) pag_w = pat_u->con_u->mem_u[i_z].pag_w; mug_w = pat_u->con_u->mem_u[i_z].mug_w; - if ( -1 == lseek(pat_u->mem_i, _ce_pag_y(i_z), SEEK_SET) ) { - fprintf(stderr, "loom: patch seek: %s\r\n", strerror(errno)); - return c3n; - } - if ( _ce_pag_y(1) != (ret_zs = read(pat_u->mem_i, mem_w, _ce_pag_y(1))) ) { + if ( _ce_pag_y(1) != + (ret_zs = pread(pat_u->mem_i, mem_w, _ce_pag_y(1), _ce_pag_y(i_z))) ) + { if ( 0 < ret_zs ) { fprintf(stderr, "loom: patch partial read: %"PRIc3_zs"\r\n", ret_zs); } @@ -533,20 +531,16 @@ _ce_patch_write_page(u3_ce_patch* pat_u, c3_w pgc_w, c3_w* mem_w) { - ssize_t ret_i; - - if ( -1 == lseek(pat_u->mem_i, _ce_pag_y(pgc_w), SEEK_SET) ) { - fprintf(stderr, "loom: patch page seek: %s\r\n", strerror(errno)); - c3_assert(0); - } + c3_zs ret_zs; - if ( _ce_pag_y(1) != (ret_i = write(pat_u->mem_i, mem_w, _ce_pag_y(1))) ) { - if ( 0 < ret_i ) { - fprintf(stderr, "loom: patch page partial write: %zu\r\n", - (size_t)ret_i); + if ( _ce_pag_y(1) != + (ret_zs = pwrite(pat_u->mem_i, mem_w, _ce_pag_y(1), _ce_pag_y(pgc_w))) ) + { + if ( 0 < ret_zs ) { + fprintf(stderr, "loom: patch partial write: %"PRIc3_zs"\r\n", ret_zs); } else { - fprintf(stderr, "loom: patch page write: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: patch write: fail: %s\r\n", strerror(errno)); } c3_assert(0); } @@ -732,21 +726,18 @@ _ce_image_resize(u3e_image* img_u, c3_w pgs_w) static void _ce_patch_apply(u3_ce_patch* pat_u) { - ssize_t ret_i; - c3_w i_w; + c3_zs ret_zs; + c3_w i_w; // resize images // _ce_image_resize(&u3P.nor_u, pat_u->con_u->nor_w); _ce_image_resize(&u3P.sou_u, pat_u->con_u->sou_w); - // seek to begining of patch and images + // seek to begining of patch // - if ( (-1 == lseek(pat_u->mem_i, 0, SEEK_SET)) - || (-1 == lseek(u3P.nor_u.fid_i, 0, SEEK_SET)) - || (-1 == lseek(u3P.sou_u.fid_i, 0, SEEK_SET)) ) - { - fprintf(stderr, "loom: patch apply seek 0: %s\r\n", strerror(errno)); + if ( -1 == lseek(pat_u->mem_i, 0, SEEK_SET) ) { + fprintf(stderr, "loom: patch apply seek: %s\r\n", strerror(errno)); c3_assert(0); } @@ -756,21 +747,21 @@ _ce_patch_apply(u3_ce_patch* pat_u) c3_w pag_w = pat_u->con_u->mem_u[i_w].pag_w; c3_w mem_w[_ce_pag_w(1)]; c3_i fid_i; - c3_z off_w; + c3_z off_z; if ( pag_w < pat_u->con_u->nor_w ) { fid_i = u3P.nor_u.fid_i; - off_w = pag_w; + off_z = _ce_pag_y(pag_w); } else { fid_i = u3P.sou_u.fid_i; - off_w = (u3P.pag_w - (pag_w + 1)); + off_z = _ce_pag_y((u3P.pag_w - (pag_w + 1))); } - if ( _ce_pag_y(1) != (ret_i = read(pat_u->mem_i, mem_w, _ce_pag_y(1))) ) { - if ( 0 < ret_i ) { - fprintf(stderr, "loom: patch apply partial read: %zu\r\n", - (size_t)ret_i); + if ( _ce_pag_y(1) != (ret_zs = read(pat_u->mem_i, mem_w, _ce_pag_y(1))) ) { + if ( 0 < ret_zs ) { + fprintf(stderr, "loom: patch apply partial read: %"PRIc3_zs"\r\n", + ret_zs); } else { fprintf(stderr, "loom: patch apply read: %s\r\n", strerror(errno)); @@ -778,14 +769,12 @@ _ce_patch_apply(u3_ce_patch* pat_u) c3_assert(0); } else { - if ( -1 == lseek(fid_i, _ce_pag_y(off_w), SEEK_SET) ) { - fprintf(stderr, "loom: patch apply seek: %s\r\n", strerror(errno)); - c3_assert(0); - } - if ( _ce_pag_y(1) != (ret_i = write(fid_i, mem_w, _ce_pag_y(1))) ) { - if ( 0 < ret_i ) { - fprintf(stderr, "loom: patch apply partial write: %zu\r\n", - (size_t)ret_i); + if ( _ce_pag_y(1) != + (ret_zs = pwrite(fid_i, mem_w, _ce_pag_y(1), off_z)) ) + { + if ( 0 < ret_zs ) { + fprintf(stderr, "loom: patch apply partial write: %"PRIc3_zs"\r\n", + ret_zs); } else { fprintf(stderr, "loom: patch apply write: %s\r\n", strerror(errno)); From b2b129c1d68a14f14419e4061fa12ef01cb3935f Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 6 Apr 2023 01:37:16 -0400 Subject: [PATCH 06/28] u3: factors out guard-page protection --- pkg/noun/events.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 05a18ad77c..8678f933ad 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -157,6 +157,20 @@ u3e_check(c3_c* cap_c) #endif #ifdef U3_GUARD_PAGE +/* _ce_ward_protect(): protect the guard page. +*/ +static inline c3_i +_ce_ward_protect(void) +{ + if ( 0 != mprotect(u3a_into(gar_pag_p), _ce_pag_y(1), PROT_NONE) ) { + fprintf(stderr, "loom: failed to protect guard page (%u): %s\r\n", + (gar_pag_p >> u3a_page), strerror(errno)); + return 1; + } + + return 0; +} + //! Place a guard page at the (approximate) middle of the free space between //! the heap and stack of the current road, bailing if memory has been //! exhausted. @@ -193,12 +207,7 @@ _ce_center_guard_page(void) goto bail; } - if ( -1 == mprotect(u3a_into(gar_pag_p), _ce_pag_y(1), PROT_NONE) ) { - fprintf(stderr, - "loom: failed to protect the guard page " - "(base address %p): %s\r\n", - u3a_into(gar_pag_p), - strerror(errno)); + if ( _ce_ward_protect() ) { goto fail; } @@ -1183,11 +1192,7 @@ u3e_yolo(void) return c3n; } - if ( 0 != mprotect(u3a_into(gar_pag_p), _ce_pag_y(1), PROT_NONE) ) { - fprintf(stderr, "loom: failed to protect guard page: %s\r\n", - strerror(errno)); - c3_assert(0); - } + c3_assert( !_ce_ward_protect() ); return c3y; } From 57bb60d443fe338c18e6cf2622eac6613402a547 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 6 Apr 2023 15:57:05 -0400 Subject: [PATCH 07/28] u3: adds coalesced page tracking, with redundant bitmap for sanity --- pkg/noun/events.c | 289 ++++++++++++++++++++++++++++++++++++++++------ pkg/noun/events.h | 1 + 2 files changed, 256 insertions(+), 34 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 8678f933ad..164972c7ad 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -262,6 +262,15 @@ u3e_fault(void* adr_v, c3_i ser_i) return 0; } + if ( (u3P.dit_w[blk_w] & (1 << bit_w)) + != (u3P.zit_w[blk_w] & (1 << bit_w)) ) + { + fprintf(stderr, "loom: page state mismatch %u cap %u hat %u\r\n", + pag_w, u3R->cap_p >> u3a_page, u3R->hat_p >> u3a_page); + c3_assert(!"page bits fault"); + } + + u3P.zit_w[blk_w] |= (1 << bit_w); // XX redundant u3P.dit_w[blk_w] |= (1 << bit_w); if ( -1 == mprotect((void *)(u3_Loom + _ce_pag_w(pag_w)), @@ -581,6 +590,14 @@ _ce_patch_save_page(u3_ce_patch* pat_u, c3_w bit_w = (pag_w & 31); if ( u3P.dit_w[blk_w] & (1 << bit_w) ) { +#if 1 // XX redundant + if ( !(u3P.zit_w[blk_w] & (1 << bit_w)) ) { + fprintf(stderr, "loom: page state mismatch %u cap %u hat %u\r\n", + pag_w, u3R->cap_p >> u3a_page, u3R->hat_p >> u3a_page); + c3_assert(!"page bits save"); + } +#endif + c3_w* mem_w = u3_Loom + _ce_pag_w(pag_w); pat_u->con_u->mem_u[pgc_w].pag_w = pag_w; @@ -591,6 +608,7 @@ _ce_patch_save_page(u3_ce_patch* pat_u, #endif _ce_patch_write_page(pat_u, pgc_w, mem_w); +#if 1 // XX redundant if ( -1 == mprotect(u3_Loom + _ce_pag_w(pag_w), _ce_pag_y(1), PROT_READ) ) @@ -601,6 +619,7 @@ _ce_patch_save_page(u3_ce_patch* pat_u, u3P.dit_w[blk_w] &= ~(1 << bit_w); pgc_w += 1; +#endif } return pgc_w; } @@ -797,52 +816,251 @@ _ce_patch_apply(u3_ce_patch* pat_u) } } -/* _ce_image_blit(): apply image to memory. +/* _ce_loom_track_north(): [pgs_w] clean, followed by [dif_w] dirty. +*/ +void +_ce_loom_track_north(c3_w pgs_w, c3_w dif_w) +{ + c3_w blk_w, bit_w, i_w = 0, max_w = pgs_w; + + for ( ; i_w < max_w; i_w++ ) { + blk_w = i_w >> 5; + bit_w = i_w & 31; +#if 1 // XX redundant + u3P.zit_w[blk_w] &= ~(1 << bit_w); + // if ( !blk_w && !bit_w ) { + // fprintf(stderr, " it_w 0 clean\r\n"); + // } +#else + u3P.dit_w[blk_w] &= ~(1 << bit_w); +#endif + } + + max_w += dif_w; + + for ( ; i_w < max_w; i_w++ ) { + blk_w = i_w >> 5; + bit_w = i_w & 31; +#if 1 // XX redundant + u3P.zit_w[blk_w] |= (1 << bit_w); +#else + u3P.dit_w[blk_w] |= (1 << bit_w); +#endif + } +} + +/* _ce_loom_track_south(): [pgs_w] clean, preceded by [dif_w] dirty. +*/ +void +_ce_loom_track_south(c3_w pgs_w, c3_w dif_w) +{ + c3_w blk_w, bit_w, i_w = u3P.pag_w - 1, max_w = u3P.pag_w - pgs_w; + + for ( ; i_w >= max_w; i_w-- ) { + blk_w = i_w >> 5; + bit_w = i_w & 31; +#if 1 // XX redundant + u3P.zit_w[blk_w] &= ~(1 << bit_w); +#else + u3P.dit_w[blk_w] &= ~(1 << bit_w); +#endif + } + + max_w -= dif_w; + + for ( ; i_w >= max_w; i_w-- ) { + blk_w = i_w >> 5; + bit_w = i_w & 31; +#if 1 // XX redundant + u3P.zit_w[blk_w] |= (1 << bit_w); +#else + u3P.dit_w[blk_w] |= (1 << bit_w); +#endif + } +} + +/* _ce_loom_protect_north(): protect/track pages from the bottom of memory. */ static void -_ce_image_blit(u3e_image* img_u, - c3_w* ptr_w, - c3_ws stp_ws) +_ce_loom_protect_north(c3_w pgs_w, c3_w old_w) { - if ( 0 == img_u->pgs_w ) { - return; + c3_w dif_w = 0; + + if ( pgs_w ) { + if ( 0 != mprotect((void*)u3_Loom, _ce_pag_y(pgs_w), PROT_READ) ) { + fprintf(stderr, "loom: pure north (%u pages): %s\r\n", + pgs_w, strerror(errno)); + c3_assert(0); + } } - ssize_t ret_i; - c3_w i_w; - c3_w siz_w = _ce_pag_y(1); + if ( old_w > pgs_w ) { + dif_w = old_w - pgs_w; - if ( -1 == lseek(img_u->fid_i, 0, SEEK_SET) ) { - fprintf(stderr, "loom: image (%s) blit seek 0: %s\r\n", - img_u->nam_c, strerror(errno)); - c3_assert(0); + if ( 0 != mprotect((void*)(u3_Loom + _ce_pag_w(pgs_w)), + _ce_pag_y(dif_w), + (PROT_READ | PROT_WRITE)) ) + { + fprintf(stderr, "loom: foul north (%u pages, %u old): %s\r\n", + pgs_w, old_w, strerror(errno)); + c3_assert(0); + } + +#ifdef U3_GUARD_PAGE + // protect guard page if clobbered + // + // NB: < pgs_w is precluded by assertion in u3e_save() + // + if ( (gar_pag_p >> u3a_page) < old_w ) { + fprintf(stderr, "loom: guard on reprotect\r\n"); + c3_assert( !_ce_ward_protect() ); + } +#endif } - for ( i_w = 0; i_w < img_u->pgs_w; i_w++ ) { - if ( siz_w != (ret_i = read(img_u->fid_i, ptr_w, siz_w)) ) { - if ( 0 < ret_i ) { - fprintf(stderr, "loom: image (%s) blit partial read: %zu\r\n", - img_u->nam_c, (size_t)ret_i); + _ce_loom_track_north(pgs_w, dif_w); +} + +/* _ce_loom_protect_south(): protect/track pages from the top of memory. +*/ +static void +_ce_loom_protect_south(c3_w pgs_w, c3_w old_w) +{ + c3_w dif_w = 0; + + if ( pgs_w ) { + if ( 0 != mprotect((void*)(u3_Loom + _ce_pag_w(u3P.pag_w - pgs_w)), + _ce_pag_y(pgs_w), + PROT_READ) ) + { + fprintf(stderr, "loom: pure south (%u pages): %s\r\n", + pgs_w, strerror(errno)); + c3_assert(0); + } + } + + if ( old_w > pgs_w ) { + c3_w off_w = u3P.pag_w - old_w; + dif_w = old_w - pgs_w; + + if ( 0 != mprotect((void*)(u3_Loom + _ce_pag_w(off_w)), + _ce_pag_y(dif_w), + (PROT_READ | PROT_WRITE)) ) + { + fprintf(stderr, "loom: foul south (%u pages, %u old): %s\r\n", + pgs_w, old_w, strerror(errno)); + c3_assert(0); + } + +#ifdef U3_GUARD_PAGE + // protect guard page if clobbered + // + // NB: >= pgs_w is precluded by assertion in u3e_save() + // + if ( (gar_pag_p >> u3a_page) >= off_w ) { + fprintf(stderr, "loom: guard on reprotect\r\n"); + c3_assert( !_ce_ward_protect() ); + } +#endif + } + + _ce_loom_track_south(pgs_w, dif_w); +} + +/* _ce_loom_blit_north(): apply pages, in order, from the bottom of memory. +*/ +static void +_ce_loom_blit_north(c3_i fid_i, c3_w pgs_w) +{ + // fprintf(stderr, "loom: blit north %u\r\n", pgs_w); + c3_w i_w; + c3_w* ptr_w; + c3_z off_z; + c3_zs ret_zs; + + for ( i_w = 0; i_w < pgs_w; i_w++ ) { + off_z = _ce_pag_y(i_w); + ptr_w = u3_Loom + _ce_pag_w(i_w); + + if ( _ce_pag_y(1) != + (ret_zs = pread(fid_i, ptr_w, _ce_pag_y(1), off_z)) ) + { + if ( 0 < ret_zs ) { + fprintf(stderr, "loom: blit north partial read: %"PRIc3_zs"\r\n", + ret_zs); } else { - fprintf(stderr, "loom: image (%s) blit read: %s\r\n", - img_u->nam_c, strerror(errno)); + fprintf(stderr, "loom: blit north read %s\r\n", strerror(errno)); } c3_assert(0); } - if ( 0 != mprotect(ptr_w, siz_w, PROT_READ) ) { +#if 1 // XX redundant + if ( 0 != mprotect(ptr_w, _ce_pag_y(1), PROT_READ) ) { fprintf(stderr, "loom: live mprotect: %s\r\n", strerror(errno)); c3_assert(0); } - c3_w pag_w = u3a_outa(ptr_w) >> u3a_page; - c3_w blk_w = pag_w >> 5; - c3_w bit_w = pag_w & 31; - u3P.dit_w[blk_w] &= ~(1 << bit_w); + { + c3_w pag_w = u3a_outa(ptr_w) >> u3a_page; + c3_w blk_w = pag_w >> 5; + c3_w bit_w = pag_w & 31; + u3P.dit_w[blk_w] &= ~(1 << bit_w); + + // if ( !blk_w && !bit_w ) { + // fprintf(stderr, "loom dit_w 0 clean\r\n"); + // } + } +#endif + } - ptr_w += stp_ws; + _ce_loom_protect_north(pgs_w, 0); +} + +/* _ce_loom_blit_south(): apply pages, reversed, from the top of memory. +*/ +static void +_ce_loom_blit_south(c3_i fid_i, c3_w pgs_w) +{ + // fprintf(stderr, "loom: blit south %u\r\n", pgs_w); + c3_w i_w; + c3_w* ptr_w; + c3_z off_z; + c3_zs ret_zs; + + for ( i_w = 0; i_w < pgs_w; i_w++ ) { + off_z = _ce_pag_y(i_w); + ptr_w = u3_Loom + _ce_pag_w(u3P.pag_w - (i_w + 1)); + + if ( _ce_pag_y(1) != + (ret_zs = pread(fid_i, ptr_w, _ce_pag_y(1), off_z)) ) + { + if ( 0 < ret_zs ) { + fprintf(stderr, "loom: blit south partial read: %"PRIc3_zs"\r\n", + ret_zs); + } + else { + fprintf(stderr, "loom: blit south read: %s\r\n", strerror(errno)); + } + c3_assert(0); + } + +#if 1 // XX redundant + if ( 0 != mprotect(ptr_w, _ce_pag_y(1), PROT_READ) ) { + fprintf(stderr, "loom: live mprotect: %s\r\n", strerror(errno)); + c3_assert(0); + } + + { + c3_w pag_w = u3a_outa(ptr_w) >> u3a_page; + c3_w blk_w = pag_w >> 5; + c3_w bit_w = pag_w & 31; + u3P.dit_w[blk_w] &= ~(1 << bit_w); + } +#endif } + + _ce_loom_protect_south(pgs_w, 0); } #ifdef U3_SNAPSHOT_VALIDATION @@ -1035,6 +1253,8 @@ void u3e_save(void) { u3_ce_patch* pat_u; + c3_w nod_w = u3P.nor_u.pgs_w; + c3_w sod_w = u3P.sou_u.pgs_w; if ( u3C.wag_w & u3o_dryrun ) { return; @@ -1077,6 +1297,10 @@ u3e_save(void) _ce_patch_free(pat_u); _ce_patch_delete(); + + _ce_loom_protect_north(u3P.nor_u.pgs_w, nod_w); + _ce_loom_protect_south(u3P.sou_u.pgs_w, sod_w); + u3e_backup(c3n); } @@ -1149,13 +1373,8 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) /* Write image files to memory; reinstate protection. */ { - _ce_image_blit(&u3P.nor_u, - u3_Loom, - _ce_pag_w(1)); - - _ce_image_blit(&u3P.sou_u, - (u3_Loom + u3C.wor_i) - _ce_pag_w(1), - -(ssize_t)_ce_pag_w(1)); + _ce_loom_blit_north(u3P.nor_u.fid_i, nor_w); + _ce_loom_blit_south(u3P.sou_u.fid_i, sou_w); u3l_log("boot: protected loom"); } @@ -1202,7 +1421,8 @@ u3e_yolo(void) void u3e_foul(void) { - memset((void*)u3P.dit_w, 0xff, sizeof(u3P.dit_w)); + memset((void*)u3P.dit_w, 0xff, sizeof(u3P.dit_w)); // XX redundant + _ce_loom_track_north(0, u3P.pag_w); } /* u3e_init(): initialize guard page tracking. @@ -1243,6 +1463,7 @@ u3e_ward(u3_post low_p, u3_post hig_p) c3_w bit_w = (pag_w & 31); u3P.dit_w[blk_w] |= (1 << bit_w); + u3P.zit_w[blk_w] |= (1 << bit_w); // XX redundant } } #endif diff --git a/pkg/noun/events.h b/pkg/noun/events.h index b4c78fe364..8855e80d37 100644 --- a/pkg/noun/events.h +++ b/pkg/noun/events.h @@ -47,6 +47,7 @@ typedef struct _u3e_pool { c3_c* dir_c; // path to c3_w dit_w[u3a_pages >> 5]; // touched since last save + c3_w zit_w[u3a_pages >> 5]; // XX redundant sanity c3_w pag_w; // number of pages (<= u3a_pages) u3e_image nor_u; // north segment u3e_image sou_u; // south segment From 59300ee6dacb48a74bedf06ab66f024c1e913405 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 6 Apr 2023 16:18:24 -0400 Subject: [PATCH 08/28] vere: adds --no-demand flag --- pkg/noun/options.h | 3 ++- pkg/vere/main.c | 16 +++++++++++++--- pkg/vere/vere.h | 1 + 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/pkg/noun/options.h b/pkg/noun/options.h index cfe6f492c5..d2e365a095 100644 --- a/pkg/noun/options.h +++ b/pkg/noun/options.h @@ -43,7 +43,8 @@ u3o_dryrun = 1 << 5, // don't touch checkpoint u3o_quiet = 1 << 6, // disable ~& u3o_hashless = 1 << 7, // disable hashboard - u3o_trace = 1 << 8 // enables trace dumping + u3o_trace = 1 << 8, // enables trace dumping + u3o_no_demand = 1 << 9 // disables demand paging }; /** Globals. diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 85e6a23c38..0344fee8aa 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -167,6 +167,7 @@ _main_init(void) // u3_Host.ops_u.has = c3y; + u3_Host.ops_u.map = c3y; u3_Host.ops_u.net = c3y; u3_Host.ops_u.lit = c3n; u3_Host.ops_u.nuu = c3n; @@ -263,6 +264,7 @@ _main_getopt(c3_i argc, c3_c** argv) { "scry-format", required_argument, NULL, 'Z' }, // { "urth-loom", required_argument, NULL, 5 }, + { "no-demand", no_argument, NULL, 6 }, // { NULL, 0, NULL, 0 }, }; @@ -272,14 +274,16 @@ _main_getopt(c3_i argc, c3_c** argv) lop_u, &lid_i)) ) { switch ( ch_i ) { - // urth-loom - // - case 5: { + case 5: { // urth-loom if (_main_readw_loom("urth-loom", &u3_Host.ops_u.lut_y)) { return c3n; } break; } + case 6: { // no-demand + u3_Host.ops_u.map = c3n; + break; + } // special args // case c3__loom: { @@ -2522,6 +2526,12 @@ main(c3_i argc, u3C.wag_w |= u3o_debug_ram; } + /* Set no-demand flag. + */ + if ( !_(u3_Host.ops_u.map) ) { + u3C.wag_w |= u3o_no_demand; + } + /* Set profile flag. */ if ( _(u3_Host.ops_u.pro) ) { diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index ca8a6da06d..6b3590bc44 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -304,6 +304,7 @@ c3_o con; // run conn c3_o doc; // dock binary in pier c3_o nuu; // new pier + c3_o map; // --no-demand (reversed) } u3_opts; /* u3_host: entire host. From 94fd70b7599b29a37b09d7231e26ae260441606e Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 6 Apr 2023 16:33:50 -0400 Subject: [PATCH 09/28] u3: implements demand paging for north.bin --- pkg/noun/events.c | 88 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 164972c7ad..2db7dcca12 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -967,6 +967,73 @@ _ce_loom_protect_south(c3_w pgs_w, c3_w old_w) _ce_loom_track_south(pgs_w, dif_w); } +/* _ce_loom_mapf_north(): map [pgs_w] of [fid_i] into the bottom of memory +** (and anonymize [old_w - pgs_w] after if needed). +** +** NB: _ce_loom_mapf_south() is possible, but it would make separate mappings +** for each page since the south segment is reversed on disk. +** in practice, the south segment is a single page (and always dirty); +** a file-backed mapping for it is just not worthwhile. +*/ +static void +_ce_loom_mapf_north(c3_i fid_i, c3_w pgs_w, c3_w old_w) +{ + c3_w dif_w = 0; + + if ( pgs_w ) { + if ( MAP_FAILED == mmap((void*)u3_Loom, + _ce_pag_y(pgs_w), + PROT_READ, + (MAP_FIXED | MAP_PRIVATE), + fid_i, 0) ) + { + fprintf(stderr, "loom: file-backed mmap failed (%u pages): %s\r\n", + pgs_w, strerror(errno)); + c3_assert(0); + } + } + + if ( old_w > pgs_w ) { + dif_w = old_w - pgs_w; + + if ( MAP_FAILED == mmap((void*)(u3_Loom + _ce_pag_w(pgs_w)), + _ce_pag_y(dif_w), + (PROT_READ | PROT_WRITE), + (MAP_ANON | MAP_FIXED | MAP_PRIVATE), + -1, 0) ) + { + fprintf(stderr, "loom: anonymous mmap failed (%u pages, %u old): %s\r\n", + pgs_w, old_w, strerror(errno)); + c3_assert(0); + } + +#ifdef U3_GUARD_PAGE + // protect guard page if clobbered + // + // NB: < pgs_w is precluded by assertion in u3e_save() + // + if ( (gar_pag_p >> u3a_page) < old_w ) { + fprintf(stderr, "loom: guard on remap\r\n"); + c3_assert( !_ce_ward_protect() ); + } +#endif + } + +#if 1 // XX redundant + { + c3_w blk_w, bit_w; + for ( c3_w i_w = 0; i_w < pgs_w; i_w++ ) { + blk_w = i_w >> 5; + bit_w = i_w & 31; + u3P.dit_w[blk_w] &= ~(1 << bit_w); + } + } +#endif + + + _ce_loom_track_north(pgs_w, dif_w); +} + /* _ce_loom_blit_north(): apply pages, in order, from the bottom of memory. */ static void @@ -1297,8 +1364,13 @@ u3e_save(void) _ce_patch_free(pat_u); _ce_patch_delete(); + if ( u3C.wag_w & u3o_no_demand ) { + _ce_loom_protect_north(u3P.nor_u.pgs_w, nod_w); + } + else { + _ce_loom_mapf_north(u3P.nor_u.fid_i, u3P.nor_u.pgs_w, nod_w); + } - _ce_loom_protect_north(u3P.nor_u.pgs_w, nod_w); _ce_loom_protect_south(u3P.sou_u.pgs_w, sod_w); u3e_backup(c3n); @@ -1373,7 +1445,13 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) /* Write image files to memory; reinstate protection. */ { - _ce_loom_blit_north(u3P.nor_u.fid_i, nor_w); + if ( u3C.wag_w & u3o_no_demand ) { + _ce_loom_blit_north(u3P.nor_u.fid_i, nor_w); + } + else { + _ce_loom_mapf_north(u3P.nor_u.fid_i, nor_w, 0); + } + _ce_loom_blit_south(u3P.sou_u.fid_i, sou_w); u3l_log("boot: protected loom"); @@ -1385,9 +1463,13 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) u3l_log("live: logical boot"); nuu_o = c3y; } - else { + else if ( u3C.wag_w & u3o_no_demand ) { u3a_print_memory(stderr, "live: loaded", _ce_pag_w(nor_w + sou_w)); } + else { + u3a_print_memory(stderr, "live: mapped", nor_w << u3a_page); + u3a_print_memory(stderr, "live: loaded", sou_w << u3a_page); + } } } From 27a098968a944098a43e65c12d7ed54fbc5b0932 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 6 Apr 2023 16:34:04 -0400 Subject: [PATCH 10/28] u3: adds MADV_DONTNEED on snapshot update --- pkg/noun/events.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 2db7dcca12..5f46c06595 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1373,6 +1373,16 @@ u3e_save(void) _ce_loom_protect_south(u3P.sou_u.pgs_w, sod_w); + { + c3_w* ptr_w = u3_Loom + _ce_pag_w(u3P.nor_u.pgs_w); + c3_w len_w = u3P.pag_w - (u3P.nor_u.pgs_w + u3P.sou_u.pgs_w); + + if ( -1 == madvise((void*)ptr_w, _ce_pag_y(len_w), MADV_DONTNEED) ) { + fprintf(stderr, "loom: madvise() failed for %u pages at %p: %s\r\n", + len_w, ptr_w, strerror(errno)); + } + } + u3e_backup(c3n); } From 6e9d6a2ea7d60ea9d1376eb6ad545a3f2520b6f6 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 6 Apr 2023 23:09:01 -0400 Subject: [PATCH 11/28] u3: refactors loom bounds in u3m_save(), with redundant sanity --- pkg/noun/events.c | 33 ++++++++++--------------- pkg/noun/events.h | 4 +-- pkg/noun/manage.c | 62 +++++++++++++++++++++++++++++++++++++++++------ pkg/noun/manage.h | 2 +- 4 files changed, 71 insertions(+), 30 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 5f46c06595..69d5e33f8e 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -627,25 +627,9 @@ _ce_patch_save_page(u3_ce_patch* pat_u, /* _ce_patch_compose(): make and write current patch. */ static u3_ce_patch* -_ce_patch_compose(void) +_ce_patch_compose(c3_w nor_w, c3_w sou_w) { c3_w pgs_w = 0; - c3_w nor_w = 0; - c3_w sou_w = 0; - - /* Calculate number of saved pages, north and south. - */ - { - c3_w nwr_w, swu_w; - - u3m_water(&nwr_w, &swu_w); - - nor_w = (nwr_w + (_ce_pag_w(1) - 1)) >> u3a_page; - sou_w = (swu_w + (_ce_pag_w(1) - 1)) >> u3a_page; - - c3_assert( ((gar_pag_p >> u3a_page) >= nor_w) - && ((gar_pag_p >> u3a_page) <= (u3a_pages - (sou_w + 1))) ); - } #ifdef U3_SNAPSHOT_VALIDATION u3K.nor_w = nor_w; @@ -1317,7 +1301,7 @@ u3e_backup(c3_o ovw_o) before we try to make another snapshot. */ void -u3e_save(void) +u3e_save(u3_post low_p, u3_post hig_p) { u3_ce_patch* pat_u; c3_w nod_w = u3P.nor_u.pgs_w; @@ -1327,8 +1311,17 @@ u3e_save(void) return; } - if ( !(pat_u = _ce_patch_compose()) ) { - return; + { + c3_w nop_w = (low_p >> u3a_page); + c3_w nor_w = (low_p + (_ce_pag_w(1) - 1)) >> u3a_page; + c3_w sop_w = hig_p >> u3a_page; + + c3_assert( ((gar_pag_p >> u3a_page) > nor_w) + && ((gar_pag_p >> u3a_page) < sop_w) ); + + if ( !(pat_u = _ce_patch_compose(nor_w, u3P.pag_w - sop_w)) ) { + return; + } } /* attempt to avoid propagating anything insane to disk */ diff --git a/pkg/noun/events.h b/pkg/noun/events.h index 8855e80d37..661b3afcbf 100644 --- a/pkg/noun/events.h +++ b/pkg/noun/events.h @@ -75,10 +75,10 @@ c3_i u3e_fault(void* adr_v, c3_i ser_i); - /* u3e_save(): + /* u3e_save(): update the checkpoint. */ void - u3e_save(void); + u3e_save(u3_post low_p, u3_post hig_p); /* u3e_live(): start the persistence system. Return c3y if no image. */ diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index 01ab6ff05d..aa920434ff 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -1027,12 +1027,31 @@ u3m_flog(c3_w gof_w) /* u3m_water(): produce watermarks. */ void -u3m_water(c3_w* low_w, c3_w* hig_w) +u3m_water(u3_post* low_p, u3_post* hig_p) { - c3_assert(u3R == &u3H->rod_u); - - *low_w = u3a_heap(u3R); - *hig_w = u3a_temp(u3R) + c3_wiseof(u3v_home); + // allow the segfault handler to fire before the road is set + // + // while not explicitly possible in the codebase, + // compiler optimizations can reorder stores + // + if ( !u3R ) { + *low_p = 0; + *hig_p = u3C.wor_i - 1; + } + // in a north road, hat points to the end of the heap + 1 word, + // while cap points to the top of the stack + // + else if ( c3y == u3a_is_north(u3R) ) { + *low_p = u3R->hat_p - 1; + *hig_p = u3R->cap_p; + } + // in a south road, hat points to the end of the heap, + // while cap points to the top of the stack + 1 word + // + else { + *low_p = u3R->cap_p - 1; + *hig_p = u3R->hat_p; + } } /* u3m_soft_top(): top-level safety wrapper. @@ -1736,7 +1755,36 @@ u3m_foul(void) void u3m_save(void) { - u3e_save(); + u3_post low_p, hig_p; + u3m_water(&low_p, &hig_p); + + c3_assert(u3R == &u3H->rod_u); + +#if 1 // XX redundant + { + c3_w low_w = u3a_heap(u3R); // old u3m_water() + c3_w hig_w = u3a_temp(u3R) + c3_wiseof(u3v_home); + + c3_w nox_w = (low_w + ((1 << u3a_page) - 1)) >> u3a_page; + c3_w sox_w = (hig_w + ((1 << u3a_page) - 1)) >> u3a_page; + + c3_w nor_w = (low_p + ((1 << u3a_page) - 1)) >> u3a_page; + c3_w sop_w = hig_p >> u3a_page; + c3_w sor_w = u3P.pag_w - sop_w; + + if ( (nox_w < nor_w) || (sox_w < sor_w) ) { + fprintf(stderr, "loom: save strange nox %u nor %u sox %u sor %u\r\n", + nox_w, nor_w, sox_w, sor_w); + } + else if ( (nox_w > nor_w) || (sox_w > sor_w) ) { + fprintf(stderr, "loom: save wrong nox %u nor %u sox %u sor %u\r\n", + nox_w, nor_w, sox_w, sor_w); + c3_assert(!"busted"); + } + } +#endif + + return u3e_save(low_p, hig_p); } /* _cm_signals(): set up interrupts, etc. @@ -2197,5 +2245,5 @@ u3m_migrate(u3v_version ver_w) u3H->ver_w = ver_w; /* extra assurance we haven't corrupted the loom before writing to disk */ u3a_loom_sane(); - u3e_save(); + u3m_save(); } diff --git a/pkg/noun/manage.h b/pkg/noun/manage.h index dd1a173fc6..4a0473f0d3 100644 --- a/pkg/noun/manage.h +++ b/pkg/noun/manage.h @@ -138,7 +138,7 @@ /* u3m_water(): produce high and low watermarks. Asserts u3R == u3H. */ void - u3m_water(c3_w *low_w, c3_w *hig_w); + u3m_water(u3_post* low_p, u3_post* hig_p); /* u3m_pretty(): dumb prettyprint to string. RETAIN. */ From 39241b957e461a98148b60ecc6400471812427ce Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 6 Apr 2023 23:22:27 -0400 Subject: [PATCH 12/28] 3: refactors loom bounds in u3m_ward(), with redundant sanity --- pkg/noun/events.c | 17 +++++++---------- pkg/noun/manage.c | 36 ++++++++++++++++++++++++++++++++++-- pkg/noun/manage.h | 5 +++++ 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 69d5e33f8e..1ae582dc59 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1528,9 +1528,12 @@ void u3e_ward(u3_post low_p, u3_post hig_p) { #ifdef U3_GUARD_PAGE - const u3p(c3_w) gar_p = gar_pag_p; + c3_w nop_w = low_p >> u3a_page; + c3_w sop_w = hig_p >> u3a_page; + u3_post gar_p = gar_pag_p; + c3_w pag_w = gar_p >> u3a_page; - if ( (low_p > gar_p) || (hig_p < gar_p) ) { + if ( !((pag_w > nop_w) && (pag_w < hig_p)) ) { _ce_center_guard_page(); if ( 0 != mprotect(u3a_into(gar_p), @@ -1542,14 +1545,8 @@ u3e_ward(u3_post low_p, u3_post hig_p) c3_assert(0); } - { - c3_w pag_w = gar_p >> u3a_page; - c3_w blk_w = (pag_w >> 5); - c3_w bit_w = (pag_w & 31); - - u3P.dit_w[blk_w] |= (1 << bit_w); - u3P.zit_w[blk_w] |= (1 << bit_w); // XX redundant - } + c3_assert( u3P.dit_w[pag_w >> 5] & (1 << (pag_w & 31)) ); + c3_assert( u3P.zit_w[pag_w >> 5] & (1 << (pag_w & 31)) ); } #endif } diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index aa920434ff..359103ac09 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -843,7 +843,6 @@ u3m_leap(c3_w pad_w) bot_p = u3R->hat_p + pad_w; rod_u = _pave_south(u3a_into(bot_p), c3_wiseof(u3a_road), len_w); - u3e_ward(rod_u->cap_p, rod_u->hat_p); #if 0 fprintf(stderr, "NPAR.hat_p: 0x%x %p, SKID.hat_p: 0x%x %p\r\n", u3R->hat_p, u3a_into(u3R->hat_p), @@ -854,7 +853,6 @@ u3m_leap(c3_w pad_w) bot_p = u3R->cap_p; rod_u = _pave_north(u3a_into(bot_p), c3_wiseof(u3a_road), len_w); - u3e_ward(rod_u->hat_p, rod_u->cap_p); #if 0 fprintf(stderr, "SPAR.hat_p: 0x%x %p, NKID.hat_p: 0x%x %p\r\n", u3R->hat_p, u3a_into(u3R->hat_p), @@ -876,6 +874,7 @@ u3m_leap(c3_w pad_w) */ { u3R = rod_u; + u3m_ward(); _pave_parts(); } #ifdef U3_MEMORY_DEBUG @@ -1787,6 +1786,39 @@ u3m_save(void) return u3e_save(low_p, hig_p); } +/* u3m_ward(): tend the guardpage. +*/ +void +u3m_ward(void) +{ + u3_post low_p, hig_p; + u3m_water(&low_p, &hig_p); + +#if 0 // XX redundant + { + c3_w low_w, hig_w; + + if ( c3y == u3a_is_north(u3R) ) { + low_w = u3R->hat_p; + hig_w = u3R->cap_p; + } + else { + low_w = u3R->cap_p; + hig_w = u3R->hat_p; + } + + if ( (low_w > (u3P.gar_w << u3a_page)) + || (hig_w < (u3P.gar_w << u3a_page)) ) + { + c3_assert( ((low_p >> u3a_page) >= u3P.gar_w) + || ((hig_p >> u3a_page) <= u3P.gar_w) ); + } + } +#endif + + return u3e_ward(low_p, hig_p); +} + /* _cm_signals(): set up interrupts, etc. */ static void diff --git a/pkg/noun/manage.h b/pkg/noun/manage.h index 4a0473f0d3..1dadc2b588 100644 --- a/pkg/noun/manage.h +++ b/pkg/noun/manage.h @@ -55,6 +55,11 @@ void u3m_save(void); + /* u3m_ward(): tend the guardpage. + */ + void + u3m_ward(void); + /* u3m_init(): start the environment. */ void From 328ccd734c75fb37cd6b95c8e2a4cc45187febaf Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 7 Apr 2023 00:16:27 -0400 Subject: [PATCH 13/28] u3: rewrites fault handling and guard page implementation --- pkg/noun/events.c | 196 ++++++++++++++++++++++------------------------ pkg/noun/events.h | 15 +++- pkg/noun/manage.c | 62 +++++++++++++-- pkg/noun/manage.h | 5 ++ 4 files changed, 165 insertions(+), 113 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 1ae582dc59..ebd627337b 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -91,9 +91,6 @@ /// Snapshotting system. u3e_pool u3e_Pool; -// Base loom offset of the guard page. -static u3p(c3_w) gar_pag_p; - #ifdef U3_SNAPSHOT_VALIDATION /* Image check. */ @@ -156,112 +153,109 @@ u3e_check(c3_c* cap_c) } #endif +/* _ce_flaw_protect(): protect page after fault. +*/ +static inline c3_i +_ce_flaw_protect(c3_w pag_w) +{ + if ( 0 != mprotect((void *)(u3_Loom + _ce_pag_w(pag_w)), + _ce_pag_y(1), + (PROT_READ | PROT_WRITE)) ) + { + fprintf(stderr, "loom: fault mprotect (%u): %s\r\n", + pag_w, strerror(errno)); + return 1; + } + + return 0; +} + #ifdef U3_GUARD_PAGE /* _ce_ward_protect(): protect the guard page. */ static inline c3_i _ce_ward_protect(void) { - if ( 0 != mprotect(u3a_into(gar_pag_p), _ce_pag_y(1), PROT_NONE) ) { + if ( 0 != mprotect((void *)(u3_Loom + _ce_pag_w(u3P.gar_w)), + _ce_pag_y(1), + PROT_NONE) ) + { fprintf(stderr, "loom: failed to protect guard page (%u): %s\r\n", - (gar_pag_p >> u3a_page), strerror(errno)); + u3P.gar_w, strerror(errno)); return 1; } return 0; } -//! Place a guard page at the (approximate) middle of the free space between -//! the heap and stack of the current road, bailing if memory has been -//! exhausted. -static c3_i -_ce_center_guard_page(void) +/* _ce_ward_post(): set the guard page. +*/ +static inline c3_i +_ce_ward_post(c3_w nop_w, c3_w sop_w) { - u3p(c3_w) bot_p, top_p; - if ( !u3R ) { - top_p = u3a_outa(u3_Loom + u3C.wor_i); - bot_p = u3a_outa(u3_Loom); - } - else if ( c3y == u3a_is_north(u3R) ) { - top_p = c3_rod(u3R->cap_p, _ce_pag_w(1)); - bot_p = c3_rop(u3R->hat_p, _ce_pag_w(1)); - } - else { - top_p = c3_rod(u3R->hat_p, _ce_pag_w(1)); - bot_p = c3_rop(u3R->cap_p, _ce_pag_w(1)); - } + u3P.gar_w = nop_w + ((sop_w - nop_w) / 2); + return _ce_ward_protect(); +} + +/* _ce_ward_clip(): hit the guard page. +*/ +static inline u3e_flaw +_ce_ward_clip(c3_w nop_w, c3_w sop_w) +{ + c3_w old_w = u3P.gar_w; - if ( top_p < bot_p + _ce_pag_w(1) ) { - fprintf(stderr, - "loom: not enough memory to recenter the guard page\r\n"); - goto bail; + if ( !u3P.gar_w || ((nop_w < u3P.gar_w) && (sop_w > u3P.gar_w)) ) { + fprintf(stderr, "loom: ward bogus (>%u %u %u<)\r\n", + nop_w, u3P.gar_w, sop_w); + return u3e_flaw_sham; } - const u3p(c3_w) old_gar_p = gar_pag_p; - const c3_w mid_p = (top_p - bot_p) / 2; - gar_pag_p = bot_p + c3_rod(mid_p, _ce_pag_w(1)); - if ( old_gar_p == gar_pag_p ) { - fprintf(stderr, - "loom: can't move the guard page to the same location" - " (base address %p)\r\n", - u3a_into(gar_pag_p)); - goto bail; + + if ( sop_w <= (nop_w + 1) ) { + return u3e_flaw_meme; } - if ( _ce_ward_protect() ) { - goto fail; + if ( _ce_ward_post(nop_w, sop_w) ) { + return u3e_flaw_base; } - return 1; + c3_assert( old_w != u3P.gar_w ); -bail: - u3m_signal(c3__meme); -fail: - return 0; + return u3e_flaw_good; } #endif /* ifdef U3_GUARD_PAGE */ -/* u3e_fault(): handle a memory event with libsigsegv protocol. +/* u3e_fault(): handle a memory fault. */ -c3_i -u3e_fault(void* adr_v, c3_i ser_i) +u3e_flaw +u3e_fault(u3_post low_p, u3_post hig_p, u3_post off_p) { - // Let the stack overflow handler run. - if ( 0 == ser_i ) { - return 0; - } - - // XX u3l_log avoid here, as it can - // cause problems when handling errors - - c3_w* adr_w = (c3_w*) adr_v; + c3_w pag_w = off_p >> u3a_page; + c3_w blk_w = pag_w >> 5; + c3_w bit_w = pag_w & 31; - if ( (adr_w < u3_Loom) || (adr_w >= (u3_Loom + u3C.wor_i)) ) { - fprintf(stderr, "address %p out of loom!\r\n", adr_w); - fprintf(stderr, "loom: [%p : %p)\r\n", u3_Loom, u3_Loom + u3C.wor_i); - c3_assert(0); - return 0; - } +#ifdef U3_GUARD_PAGE + if ( pag_w == u3P.gar_w ) { + u3e_flaw fal_e = _ce_ward_clip(low_p >> u3a_page, hig_p >> u3a_page); - u3p(c3_w) adr_p = u3a_outa(adr_w); - c3_w pag_w = adr_p >> u3a_page; - c3_w blk_w = (pag_w >> 5); - c3_w bit_w = (pag_w & 31); + if ( u3e_flaw_good != fal_e ) { + return fal_e; + } -#ifdef U3_GUARD_PAGE - // The fault happened in the guard page. - if ( gar_pag_p <= adr_p && adr_p < gar_pag_p + _ce_pag_w(1) ) { - if ( 0 == _ce_center_guard_page() ) { - return 0; + if ( !(u3P.dit_w[blk_w] & (1 << bit_w)) ) { + fprintf(stderr, "loom: strange guard (%d)\r\n", pag_w); + return u3e_flaw_sham; } + + c3_assert( u3P.zit_w[blk_w] & (1 << bit_w) ); // XX redundant } else -#endif /* ifdef U3_GUARD_PAGE */ - if ( 0 != (u3P.dit_w[blk_w] & (1 << bit_w)) ) { - fprintf(stderr, "strange page: %d, at %p, off %x\r\n", pag_w, adr_w, adr_p); - c3_assert(0); - return 0; +#endif + if ( u3P.dit_w[blk_w] & (1 << bit_w) ) { + fprintf(stderr, "loom: strange page (%d): %x\r\n", pag_w, off_p); + return u3e_flaw_sham; } +#if 1 // XX redundant if ( (u3P.dit_w[blk_w] & (1 << bit_w)) != (u3P.zit_w[blk_w] & (1 << bit_w)) ) { @@ -270,19 +264,16 @@ u3e_fault(void* adr_v, c3_i ser_i) c3_assert(!"page bits fault"); } - u3P.zit_w[blk_w] |= (1 << bit_w); // XX redundant + u3P.zit_w[blk_w] |= (1 << bit_w); +#endif + u3P.dit_w[blk_w] |= (1 << bit_w); - if ( -1 == mprotect((void *)(u3_Loom + _ce_pag_w(pag_w)), - _ce_pag_y(1), - (PROT_READ | PROT_WRITE)) ) - { - fprintf(stderr, "loom: fault mprotect: %s\r\n", strerror(errno)); - c3_assert(0); - return 0; + if ( _ce_flaw_protect(pag_w) ) { + return u3e_flaw_base; } - return 1; + return u3e_flaw_good; } /* _ce_image_open(): open or create image. @@ -895,7 +886,7 @@ _ce_loom_protect_north(c3_w pgs_w, c3_w old_w) // // NB: < pgs_w is precluded by assertion in u3e_save() // - if ( (gar_pag_p >> u3a_page) < old_w ) { + if ( u3P.gar_w < old_w ) { fprintf(stderr, "loom: guard on reprotect\r\n"); c3_assert( !_ce_ward_protect() ); } @@ -941,7 +932,7 @@ _ce_loom_protect_south(c3_w pgs_w, c3_w old_w) // // NB: >= pgs_w is precluded by assertion in u3e_save() // - if ( (gar_pag_p >> u3a_page) >= off_w ) { + if ( u3P.gar_w >= off_w ) { fprintf(stderr, "loom: guard on reprotect\r\n"); c3_assert( !_ce_ward_protect() ); } @@ -996,7 +987,7 @@ _ce_loom_mapf_north(c3_i fid_i, c3_w pgs_w, c3_w old_w) // // NB: < pgs_w is precluded by assertion in u3e_save() // - if ( (gar_pag_p >> u3a_page) < old_w ) { + if ( u3P.gar_w < old_w ) { fprintf(stderr, "loom: guard on remap\r\n"); c3_assert( !_ce_ward_protect() ); } @@ -1316,8 +1307,7 @@ u3e_save(u3_post low_p, u3_post hig_p) c3_w nor_w = (low_p + (_ce_pag_w(1) - 1)) >> u3a_page; c3_w sop_w = hig_p >> u3a_page; - c3_assert( ((gar_pag_p >> u3a_page) > nor_w) - && ((gar_pag_p >> u3a_page) < sop_w) ); + c3_assert( (u3P.gar_w > nop_w) && (u3P.gar_w < sop_w) ); if ( !(pat_u = _ce_patch_compose(nor_w, u3P.pag_w - sop_w)) ) { return; @@ -1473,6 +1463,10 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) u3a_print_memory(stderr, "live: mapped", nor_w << u3a_page); u3a_print_memory(stderr, "live: loaded", sou_w << u3a_page); } + +#ifdef U3_GUARD_PAGE + c3_assert( !_ce_ward_post(nor_w, u3P.pag_w - sou_w) ); +#endif } } @@ -1510,16 +1504,20 @@ u3e_foul(void) _ce_loom_track_north(0, u3P.pag_w); } -/* u3e_init(): initialize guard page tracking. +/* u3e_init(): initialize guard page tracking, dirty loom */ void u3e_init(void) { u3P.pag_w = u3C.wor_i >> u3a_page; + u3e_foul(); + #ifdef U3_GUARD_PAGE - _ce_center_guard_page(); + c3_assert( !_ce_ward_post(0, u3P.pag_w) ); #endif + + u3e_foul(); } /* u3e_ward(): reposition guard page if needed. @@ -1530,21 +1528,11 @@ u3e_ward(u3_post low_p, u3_post hig_p) #ifdef U3_GUARD_PAGE c3_w nop_w = low_p >> u3a_page; c3_w sop_w = hig_p >> u3a_page; - u3_post gar_p = gar_pag_p; - c3_w pag_w = gar_p >> u3a_page; + c3_w pag_w = u3P.gar_w; if ( !((pag_w > nop_w) && (pag_w < hig_p)) ) { - _ce_center_guard_page(); - - if ( 0 != mprotect(u3a_into(gar_p), - _ce_pag_y(1), - (PROT_READ | PROT_WRITE)) ) - { - fprintf(stderr, "loom: failed to unprotect old guard page: %s\r\n", - strerror(errno)); - c3_assert(0); - } - + c3_assert( !_ce_ward_post(nop_w, sop_w) ); + c3_assert( !_ce_flaw_protect(pag_w) ); c3_assert( u3P.dit_w[pag_w >> 5] & (1 << (pag_w & 31)) ); c3_assert( u3P.zit_w[pag_w >> 5] & (1 << (pag_w & 31)) ); } diff --git a/pkg/noun/events.h b/pkg/noun/events.h index 661b3afcbf..acd7dbdf9c 100644 --- a/pkg/noun/events.h +++ b/pkg/noun/events.h @@ -49,10 +49,19 @@ c3_w dit_w[u3a_pages >> 5]; // touched since last save c3_w zit_w[u3a_pages >> 5]; // XX redundant sanity c3_w pag_w; // number of pages (<= u3a_pages) + c3_w gar_w; // guard page u3e_image nor_u; // north segment u3e_image sou_u; // south segment } u3e_pool; + /* u3e_flaw: loom fault result. + */ + typedef enum { + u3e_flaw_sham = 0, // bogus state + u3e_flaw_base = 1, // vm fail (mprotect) + u3e_flaw_meme = 2, // bail:meme + u3e_flaw_good = 3 // handled + } u3e_flaw; /** Globals. **/ @@ -70,10 +79,10 @@ c3_o u3e_backup(c3_o ovw_o); - /* u3e_fault(): handle a memory event with libsigsegv protocol. + /* u3e_fault(): handle a memory fault. */ - c3_i - u3e_fault(void* adr_v, c3_i ser_i); + u3e_flaw + u3e_fault(u3_post low_p, u3_post hig_p, u3_post off_p); /* u3e_save(): update the checkpoint. */ diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index 359103ac09..51bc0bea79 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -1737,6 +1737,60 @@ u3m_backup(c3_o ovw_o) return u3e_backup(ovw_o); } +/* u3m_fault(): handle a memory event with libsigsegv protocol. +*/ +c3_i +u3m_fault(void* adr_v, c3_i ser_i) +{ + c3_w* adr_w = (c3_w*)adr_v; + u3_post low_p, hig_p; + + // let the stack overflow handler run. + // + if ( 0 == ser_i ) { + return 0; + } + // this could be avoided by registering the loom bounds in libsigsegv + // + else if ( (adr_w < u3_Loom) || (adr_w >= (u3_Loom + u3C.wor_i)) ) { + fprintf(stderr, "loom: external fault: %p (%p : %p)\r\n\r\n", + adr_w, u3_Loom, u3_Loom + u3C.wor_i); + c3_assert(0); + return 0; + } + + u3m_water(&low_p, &hig_p); + + switch ( u3e_fault(low_p, hig_p, u3a_outa(adr_w)) ) { + // page tracking invariants violated, fatal + // + case u3e_flaw_sham: { + c3_assert(0); + return 0; + } + + // virtual memory failure (protections) + // + // XX s/b recoverable, need to u3m_signal() a new mote + // + case u3e_flaw_base: { + c3_assert(0); + return 0; + } + + // loom limits exceeded, recoverable + // + case u3e_flaw_meme: { + u3m_signal(c3__meme); // doesn't return + return 1; + } + + case u3e_flaw_good: return 1; + } + + c3_assert(!"unpossible"); +} + /* u3m_foul(): dirty all pages and disable tracking. */ void @@ -1794,7 +1848,7 @@ u3m_ward(void) u3_post low_p, hig_p; u3m_water(&low_p, &hig_p); -#if 0 // XX redundant +#if 1 // XX redundant { c3_w low_w, hig_w; @@ -1824,7 +1878,7 @@ u3m_ward(void) static void _cm_signals(void) { - if ( 0 != sigsegv_install_handler(u3e_fault) ) { + if ( 0 != sigsegv_install_handler(u3m_fault) ) { u3l_log("boot: sigsegv install failed"); exit(1); } @@ -2010,10 +2064,6 @@ u3m_boot(c3_c* dir_c, size_t len_i) */ u3m_pave(nuu_o); - /* Place the guard page. - */ - u3e_init(); - /* Initialize the jet system. */ { diff --git a/pkg/noun/manage.h b/pkg/noun/manage.h index 1dadc2b588..b675cb139d 100644 --- a/pkg/noun/manage.h +++ b/pkg/noun/manage.h @@ -40,6 +40,11 @@ c3_i u3m_bail(c3_m how_m) __attribute__((noreturn)); + /* u3m_fault(): handle a memory event with libsigsegv protocol. + */ + c3_i + u3m_fault(void* adr_v, c3_i ser_i); + /* u3m_foul(): dirty all pages and disable tracking. */ void From fda47589c23954d12de2fa15aa1e9d6acee509ba Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 7 Apr 2023 00:44:26 -0400 Subject: [PATCH 14/28] u3: document snapshot system invariants --- pkg/noun/events.c | 53 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index ebd627337b..2f7cb13e10 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -7,7 +7,7 @@ //! - page: 16KB chunk of the loom. //! - north segment (u3e_image, north.bin): low contiguous loom pages, //! (in practice, the home road heap). indexed from low to high: -//! in-order on disk. +//! in-order on disk. in a file-backed mapping by default. //! - south segment (u3e_image, south.bin): high contiguous loom pages, //! (in practice, the home road stack). indexed from high to low: //! reversed on disk. @@ -20,8 +20,8 @@ //! - with the loom already mapped, all pages are marked dirty in a bitmap. //! - if snapshot is missing or partial, empty segments are created. //! - if a patch is present, it's applied (crash recovery). -//! - snapshot segments are copied onto the loom; all included pages -//! are marked clean and protected (read-only). +//! - snapshot segments are mapped or copied onto the loom; +//! all included pages are marked clean and protected (read-only). //! //! #### page faults (u3e_fault()) //! @@ -47,27 +47,48 @@ //! contiguous free space). //! - patch pages are written to memory.bin, metadata to control.bin. //! - the patch is applied to the snapshot segments, in-place. -//! - patch files are deleted. +//! - segments are fsync'd; patch files are deleted. +//! - memory protections (and file-backed mappings) are re-established. +//! +//! ### invariants +//! +//! definitions: +//! - a clean page is PROT_READ and 0 in the bitmap +//! - a dirty page is (PROT_READ|PROT_WRITE) and 1 in the bitmap +//! - the guard page is PROT_NONE and 1 in the bitmap +//! +//! assumptions: +//! - all memory access patterns are outside-in, a page at a time +//! - ad-hoc exceptions are supported by calling u3e_ward() +//! +//! - there is a single guard page, between the segments +//! - dirty pages only become clean by being: +//! - loaded from a snapshot during initialization +//! - present in a snapshot after save +//! - clean pages only become dirty by being: +//! - modified (and caught by the fault handler) +//! - orphaned due to segment truncation (explicitly dirtied) +//! - at points of quiescence (initialization, after save) +//! - all pages of the north and south segments are clean +//! - all other pages are dirty //! //! ### limitations //! //! - loom page size is fixed (16 KB), and must be a multiple of the -//! system page size. (can the size vary at runtime give south.bin's -//! reversed order? alternately, if system page size > ours, the fault -//! handler could dirty N pages at a time.) -//! - update atomicity is suspect: patch application must either -//! completely succeed or leave on-disk segments intact. unapplied -//! patches can be discarded (triggering event replay), but once -//! patch application begins it must succeed. -//! may require integration into the overall signal-handling regime. -//! - any errors are handled with assertions; failed/partial writes are not -//! retried. +//! system page size. +//! - update atomicity is crucial: +//! - patch application must either completely succeed or +//! leave on-disk segments (memory image) intact. +//! - unapplied patches can be discarded (triggering event replay), +//! but once patch application begins it must succeed. +//! - may require integration into the overall signal-handling regime. +//! - any errors are handled with assertions; error messages are poor; +//! failed/partial writes are not retried. //! //! ### enhancements //! //! - use platform specific page fault mechanism (mach rpc, userfaultfd, &c). -//! - implement demand paging / heuristic page-out. -//! - parallelism +//! - parallelism (conflicts with demand paging) //! #include "events.h" From 00d96fb31b3fca4e72ed8fdbe22c5db61947fd7e Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 11 Apr 2023 14:16:46 -0400 Subject: [PATCH 15/28] TMP continue on serf ipc eof --- pkg/vere/lord.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/vere/lord.c b/pkg/vere/lord.c index bdb68b4981..54598df4bf 100644 --- a/pkg/vere/lord.c +++ b/pkg/vere/lord.c @@ -1099,7 +1099,9 @@ _lord_on_serf_bail(void* ptr_v, u3_lord* god_u = ptr_v; if ( UV_EOF == err_i ) { - u3l_log("pier: serf unexpectedly shut down"); + // u3l_log("pier: serf unexpectedly shut down"); + u3l_log("pier: EOF"); + return; } else { u3l_log("pier: serf error: %s", err_c); From ddc43657afadff33bfd9082cdcc32e1641639243 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 12 Apr 2023 18:18:13 -0400 Subject: [PATCH 16/28] TMP enable snapshot validation --- pkg/noun/events.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 2f7cb13e10..1f41b30cf5 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -103,6 +103,8 @@ #include "retrieve.h" #include "types.h" +#define U3_SNAPSHOT_VALIDATION + /* _ce_pag_w: word position of given page ** _ce_pag_y: byte position of given page */ From ed81232bb511c7199c06295d3e6e52f0cfa7b84c Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 12 Apr 2023 18:32:18 -0400 Subject: [PATCH 17/28] u3: removes redundant dirty page tracking bitmap --- pkg/noun/events.c | 107 +++------------------------------------------- pkg/noun/events.h | 1 - 2 files changed, 5 insertions(+), 103 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 1f41b30cf5..4d9e23a370 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -268,8 +268,6 @@ u3e_fault(u3_post low_p, u3_post hig_p, u3_post off_p) fprintf(stderr, "loom: strange guard (%d)\r\n", pag_w); return u3e_flaw_sham; } - - c3_assert( u3P.zit_w[blk_w] & (1 << bit_w) ); // XX redundant } else #endif @@ -278,18 +276,6 @@ u3e_fault(u3_post low_p, u3_post hig_p, u3_post off_p) return u3e_flaw_sham; } -#if 1 // XX redundant - if ( (u3P.dit_w[blk_w] & (1 << bit_w)) - != (u3P.zit_w[blk_w] & (1 << bit_w)) ) - { - fprintf(stderr, "loom: page state mismatch %u cap %u hat %u\r\n", - pag_w, u3R->cap_p >> u3a_page, u3R->hat_p >> u3a_page); - c3_assert(!"page bits fault"); - } - - u3P.zit_w[blk_w] |= (1 << bit_w); -#endif - u3P.dit_w[blk_w] |= (1 << bit_w); if ( _ce_flaw_protect(pag_w) ) { @@ -604,36 +590,18 @@ _ce_patch_save_page(u3_ce_patch* pat_u, c3_w bit_w = (pag_w & 31); if ( u3P.dit_w[blk_w] & (1 << bit_w) ) { -#if 1 // XX redundant - if ( !(u3P.zit_w[blk_w] & (1 << bit_w)) ) { - fprintf(stderr, "loom: page state mismatch %u cap %u hat %u\r\n", - pag_w, u3R->cap_p >> u3a_page, u3R->hat_p >> u3a_page); - c3_assert(!"page bits save"); - } -#endif - c3_w* mem_w = u3_Loom + _ce_pag_w(pag_w); pat_u->con_u->mem_u[pgc_w].pag_w = pag_w; pat_u->con_u->mem_u[pgc_w].mug_w = u3r_mug_words(mem_w, _ce_pag_w(1)); #if 0 - u3l_log("protect a: page %d", pag_w); + fprintf(stderr, "loom: save page %d %x\r\n", + pag_w, pat_u->con_u->mem_u[pgc_w].mug_w); #endif _ce_patch_write_page(pat_u, pgc_w, mem_w); -#if 1 // XX redundant - if ( -1 == mprotect(u3_Loom + _ce_pag_w(pag_w), - _ce_pag_y(1), - PROT_READ) ) - { - fprintf(stderr, "loom: patch mprotect: %s\r\n", strerror(errno)); - c3_assert(0); - } - - u3P.dit_w[blk_w] &= ~(1 << bit_w); pgc_w += 1; -#endif } return pgc_w; } @@ -682,6 +650,8 @@ _ce_patch_compose(c3_w nor_w, c3_w sou_w) pgc_w = _ce_patch_save_page(pat_u, (u3P.pag_w - (i_w + 1)), pgc_w); } + c3_assert( pgc_w == pgs_w ); + pat_u->con_u->nor_w = nor_w; pat_u->con_u->sou_w = sou_w; pat_u->con_u->pgs_w = pgc_w; @@ -824,14 +794,7 @@ _ce_loom_track_north(c3_w pgs_w, c3_w dif_w) for ( ; i_w < max_w; i_w++ ) { blk_w = i_w >> 5; bit_w = i_w & 31; -#if 1 // XX redundant - u3P.zit_w[blk_w] &= ~(1 << bit_w); - // if ( !blk_w && !bit_w ) { - // fprintf(stderr, " it_w 0 clean\r\n"); - // } -#else u3P.dit_w[blk_w] &= ~(1 << bit_w); -#endif } max_w += dif_w; @@ -839,11 +802,7 @@ _ce_loom_track_north(c3_w pgs_w, c3_w dif_w) for ( ; i_w < max_w; i_w++ ) { blk_w = i_w >> 5; bit_w = i_w & 31; -#if 1 // XX redundant - u3P.zit_w[blk_w] |= (1 << bit_w); -#else u3P.dit_w[blk_w] |= (1 << bit_w); -#endif } } @@ -857,11 +816,7 @@ _ce_loom_track_south(c3_w pgs_w, c3_w dif_w) for ( ; i_w >= max_w; i_w-- ) { blk_w = i_w >> 5; bit_w = i_w & 31; -#if 1 // XX redundant - u3P.zit_w[blk_w] &= ~(1 << bit_w); -#else u3P.dit_w[blk_w] &= ~(1 << bit_w); -#endif } max_w -= dif_w; @@ -869,11 +824,7 @@ _ce_loom_track_south(c3_w pgs_w, c3_w dif_w) for ( ; i_w >= max_w; i_w-- ) { blk_w = i_w >> 5; bit_w = i_w & 31; -#if 1 // XX redundant - u3P.zit_w[blk_w] |= (1 << bit_w); -#else u3P.dit_w[blk_w] |= (1 << bit_w); -#endif } } @@ -1017,18 +968,6 @@ _ce_loom_mapf_north(c3_i fid_i, c3_w pgs_w, c3_w old_w) #endif } -#if 1 // XX redundant - { - c3_w blk_w, bit_w; - for ( c3_w i_w = 0; i_w < pgs_w; i_w++ ) { - blk_w = i_w >> 5; - bit_w = i_w & 31; - u3P.dit_w[blk_w] &= ~(1 << bit_w); - } - } -#endif - - _ce_loom_track_north(pgs_w, dif_w); } @@ -1059,24 +998,6 @@ _ce_loom_blit_north(c3_i fid_i, c3_w pgs_w) } c3_assert(0); } - -#if 1 // XX redundant - if ( 0 != mprotect(ptr_w, _ce_pag_y(1), PROT_READ) ) { - fprintf(stderr, "loom: live mprotect: %s\r\n", strerror(errno)); - c3_assert(0); - } - - { - c3_w pag_w = u3a_outa(ptr_w) >> u3a_page; - c3_w blk_w = pag_w >> 5; - c3_w bit_w = pag_w & 31; - u3P.dit_w[blk_w] &= ~(1 << bit_w); - - // if ( !blk_w && !bit_w ) { - // fprintf(stderr, "loom dit_w 0 clean\r\n"); - // } - } -#endif } _ce_loom_protect_north(pgs_w, 0); @@ -1109,20 +1030,6 @@ _ce_loom_blit_south(c3_i fid_i, c3_w pgs_w) } c3_assert(0); } - -#if 1 // XX redundant - if ( 0 != mprotect(ptr_w, _ce_pag_y(1), PROT_READ) ) { - fprintf(stderr, "loom: live mprotect: %s\r\n", strerror(errno)); - c3_assert(0); - } - - { - c3_w pag_w = u3a_outa(ptr_w) >> u3a_page; - c3_w blk_w = pag_w >> 5; - c3_w bit_w = pag_w & 31; - u3P.dit_w[blk_w] &= ~(1 << bit_w); - } -#endif } _ce_loom_protect_south(pgs_w, 0); @@ -1523,8 +1430,7 @@ u3e_yolo(void) void u3e_foul(void) { - memset((void*)u3P.dit_w, 0xff, sizeof(u3P.dit_w)); // XX redundant - _ce_loom_track_north(0, u3P.pag_w); + memset((void*)u3P.dit_w, 0xff, sizeof(u3P.dit_w)); } /* u3e_init(): initialize guard page tracking, dirty loom @@ -1539,8 +1445,6 @@ u3e_init(void) #ifdef U3_GUARD_PAGE c3_assert( !_ce_ward_post(0, u3P.pag_w) ); #endif - - u3e_foul(); } /* u3e_ward(): reposition guard page if needed. @@ -1557,7 +1461,6 @@ u3e_ward(u3_post low_p, u3_post hig_p) c3_assert( !_ce_ward_post(nop_w, sop_w) ); c3_assert( !_ce_flaw_protect(pag_w) ); c3_assert( u3P.dit_w[pag_w >> 5] & (1 << (pag_w & 31)) ); - c3_assert( u3P.zit_w[pag_w >> 5] & (1 << (pag_w & 31)) ); } #endif } diff --git a/pkg/noun/events.h b/pkg/noun/events.h index acd7dbdf9c..3858ff9079 100644 --- a/pkg/noun/events.h +++ b/pkg/noun/events.h @@ -47,7 +47,6 @@ typedef struct _u3e_pool { c3_c* dir_c; // path to c3_w dit_w[u3a_pages >> 5]; // touched since last save - c3_w zit_w[u3a_pages >> 5]; // XX redundant sanity c3_w pag_w; // number of pages (<= u3a_pages) c3_w gar_w; // guard page u3e_image nor_u; // north segment From 2ba8d4dc83f6937530f02eef071244ba565994b2 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 12 Apr 2023 18:42:36 -0400 Subject: [PATCH 18/28] u3: refactors page pointer/size macros --- pkg/noun/events.c | 175 +++++++++++++++++++++------------------------- 1 file changed, 80 insertions(+), 95 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 4d9e23a370..536c279f1a 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -105,15 +105,27 @@ #define U3_SNAPSHOT_VALIDATION -/* _ce_pag_w: word position of given page -** _ce_pag_y: byte position of given page +/* _ce_len: byte length of pages +** _ce_len_words: word length of pages +** _ce_page: byte length of a single page +** _ce_ptr: void pointer to a page */ -#define _ce_pag_w(i) ((size_t)(i) << u3a_page) -#define _ce_pag_y(i) ((size_t)(i) << (u3a_page + 2)) +#define _ce_len(i) ((size_t)(i) << (u3a_page + 2)) +#define _ce_len_words(i) ((size_t)(i) << u3a_page) +#define _ce_page _ce_len(1) +#define _ce_ptr(i) ((void *)((c3_c*)u3_Loom + _ce_len(i))) /// Snapshotting system. u3e_pool u3e_Pool; +static c3_l +_ce_mug_page(void* ptr_v) +{ + // XX trailing zeros + // return u3r_mug_bytes(ptr_v, _ce_page); + return u3r_mug_words(ptr_v, _ce_len_words(1)); +} + #ifdef U3_SNAPSHOT_VALIDATION /* Image check. */ @@ -123,17 +135,6 @@ struct { c3_w mug_w[u3a_pages]; } u3K; -/* _ce_check_page(): checksum page. -*/ -static c3_w -_ce_check_page(c3_w pag_w) -{ - c3_w* mem_w = u3_Loom + _ce_pag_w(pag_w); - c3_w mug_w = u3r_mug_words(mem_w, _ce_pag_w(1)); - - return mug_w; -} - /* u3e_check(): compute a checksum on all memory within the watermarks. */ void @@ -147,8 +148,8 @@ u3e_check(c3_c* cap_c) u3m_water(&nwr_w, &swu_w); - nor_w = (nwr_w + (_ce_pag_w(1) - 1)) >> u3a_page; - sou_w = (swu_w + (_ce_pag_w(1) - 1)) >> u3a_page; + nor_w = (nwr_w + (_ce_len_words(1) - 1)) >> u3a_page; + sou_w = (swu_w + (_ce_len_words(1) - 1)) >> u3a_page; } /* Count dirty pages. @@ -158,14 +159,14 @@ u3e_check(c3_c* cap_c) sum_w = 0; for ( i_w = 0; i_w < nor_w; i_w++ ) { - mug_w = _ce_check_page(i_w); + mug_w = _ce_mug_page(_ce_ptr(i_w)); if ( strcmp(cap_c, "boot") ) { c3_assert(mug_w == u3K.mug_w[i_w]); } sum_w += mug_w; } for ( i_w = 0; i_w < sou_w; i_w++ ) { - mug_w = _ce_check_page((u3P.pag_w - (i_w + 1))); + mug_w = _ce_mug_page(_ce_ptr((u3P.pag_w - (i_w + 1)))); if ( strcmp(cap_c, "boot") ) { c3_assert(mug_w == u3K.mug_w[(u3P.pag_w - (i_w + 1))]); } @@ -181,10 +182,7 @@ u3e_check(c3_c* cap_c) static inline c3_i _ce_flaw_protect(c3_w pag_w) { - if ( 0 != mprotect((void *)(u3_Loom + _ce_pag_w(pag_w)), - _ce_pag_y(1), - (PROT_READ | PROT_WRITE)) ) - { + if ( 0 != mprotect(_ce_ptr(pag_w), _ce_page, (PROT_READ | PROT_WRITE)) ) { fprintf(stderr, "loom: fault mprotect (%u): %s\r\n", pag_w, strerror(errno)); return 1; @@ -199,10 +197,7 @@ _ce_flaw_protect(c3_w pag_w) static inline c3_i _ce_ward_protect(void) { - if ( 0 != mprotect((void *)(u3_Loom + _ce_pag_w(u3P.gar_w)), - _ce_pag_y(1), - PROT_NONE) ) - { + if ( 0 != mprotect(_ce_ptr(u3P.gar_w), _ce_page, PROT_NONE) ) { fprintf(stderr, "loom: failed to protect guard page (%u): %s\r\n", u3P.gar_w, strerror(errno)); return 1; @@ -317,13 +312,13 @@ _ce_image_open(u3e_image* img_u) } else { c3_z siz_z = buf_u.st_size; - c3_z pgs_z = (siz_z + (_ce_pag_y(1) - 1)) >> (u3a_page + 2); + c3_z pgs_z = (siz_z + (_ce_page - 1)) >> (u3a_page + 2); if ( !siz_z ) { return c3y; } else { - if ( siz_z != _ce_pag_y(pgs_z) ) { + if ( siz_z != _ce_len(pgs_z) ) { fprintf(stderr, "%s: corrupt size %zu\r\n", ful_c, siz_z); return c3n; } @@ -438,7 +433,7 @@ static c3_o _ce_patch_verify(u3_ce_patch* pat_u) { c3_w pag_w, mug_w; - c3_w mem_w[_ce_pag_w(1)]; + c3_y buf_y[_ce_page]; c3_zs ret_zs; if ( U3E_VERLAT != pat_u->con_u->ver_w ) { @@ -452,8 +447,8 @@ _ce_patch_verify(u3_ce_patch* pat_u) pag_w = pat_u->con_u->mem_u[i_z].pag_w; mug_w = pat_u->con_u->mem_u[i_z].mug_w; - if ( _ce_pag_y(1) != - (ret_zs = pread(pat_u->mem_i, mem_w, _ce_pag_y(1), _ce_pag_y(i_z))) ) + if ( _ce_page != + (ret_zs = pread(pat_u->mem_i, buf_y, _ce_page, _ce_len(i_z))) ) { if ( 0 < ret_zs ) { fprintf(stderr, "loom: patch partial read: %"PRIc3_zs"\r\n", ret_zs); @@ -465,7 +460,7 @@ _ce_patch_verify(u3_ce_patch* pat_u) } { - c3_w nug_w = u3r_mug_words(mem_w, _ce_pag_w(1)); + c3_w nug_w = _ce_mug_page(buf_y); if ( mug_w != nug_w ) { fprintf(stderr, "loom: patch mug mismatch" @@ -551,8 +546,8 @@ _ce_patch_write_page(u3_ce_patch* pat_u, { c3_zs ret_zs; - if ( _ce_pag_y(1) != - (ret_zs = pwrite(pat_u->mem_i, mem_w, _ce_pag_y(1), _ce_pag_y(pgc_w))) ) + if ( _ce_page != + (ret_zs = pwrite(pat_u->mem_i, mem_w, _ce_page, _ce_len(pgc_w))) ) { if ( 0 < ret_zs ) { fprintf(stderr, "loom: patch partial write: %"PRIc3_zs"\r\n", ret_zs); @@ -586,14 +581,14 @@ _ce_patch_save_page(u3_ce_patch* pat_u, c3_w pag_w, c3_w pgc_w) { - c3_w blk_w = (pag_w >> 5); - c3_w bit_w = (pag_w & 31); + c3_w blk_w = (pag_w >> 5); + c3_w bit_w = (pag_w & 31); if ( u3P.dit_w[blk_w] & (1 << bit_w) ) { - c3_w* mem_w = u3_Loom + _ce_pag_w(pag_w); + c3_w* mem_w = _ce_ptr(pag_w); pat_u->con_u->mem_u[pgc_w].pag_w = pag_w; - pat_u->con_u->mem_u[pgc_w].mug_w = u3r_mug_words(mem_w, _ce_pag_w(1)); + pat_u->con_u->mem_u[pgc_w].mug_w = _ce_mug_page(mem_w); #if 0 fprintf(stderr, "loom: save page %d %x\r\n", @@ -696,7 +691,7 @@ _ce_image_sync(u3e_image* img_u) static void _ce_image_resize(u3e_image* img_u, c3_w pgs_w) { - c3_z off_z = _ce_pag_y(pgs_w); + c3_z off_z = _ce_len(pgs_w); off_t off_i = (off_t)off_z; if ( img_u->pgs_w > pgs_w ) { @@ -741,20 +736,20 @@ _ce_patch_apply(u3_ce_patch* pat_u) // for ( i_w = 0; i_w < pat_u->con_u->pgs_w; i_w++ ) { c3_w pag_w = pat_u->con_u->mem_u[i_w].pag_w; - c3_w mem_w[_ce_pag_w(1)]; + c3_w buf_y[_ce_page]; c3_i fid_i; c3_z off_z; if ( pag_w < pat_u->con_u->nor_w ) { fid_i = u3P.nor_u.fid_i; - off_z = _ce_pag_y(pag_w); + off_z = _ce_len(pag_w); } else { fid_i = u3P.sou_u.fid_i; - off_z = _ce_pag_y((u3P.pag_w - (pag_w + 1))); + off_z = _ce_len((u3P.pag_w - (pag_w + 1))); } - if ( _ce_pag_y(1) != (ret_zs = read(pat_u->mem_i, mem_w, _ce_pag_y(1))) ) { + if ( _ce_page != (ret_zs = read(pat_u->mem_i, buf_y, _ce_page)) ) { if ( 0 < ret_zs ) { fprintf(stderr, "loom: patch apply partial read: %"PRIc3_zs"\r\n", ret_zs); @@ -765,8 +760,8 @@ _ce_patch_apply(u3_ce_patch* pat_u) c3_assert(0); } else { - if ( _ce_pag_y(1) != - (ret_zs = pwrite(fid_i, mem_w, _ce_pag_y(1), off_z)) ) + if ( _ce_page != + (ret_zs = pwrite(fid_i, buf_y, _ce_page, off_z)) ) { if ( 0 < ret_zs ) { fprintf(stderr, "loom: patch apply partial write: %"PRIc3_zs"\r\n", @@ -779,7 +774,7 @@ _ce_patch_apply(u3_ce_patch* pat_u) } } #if 0 - u3l_log("apply: %d, %x", pag_w, u3r_mug_words(mem_w, _ce_pag_w(1))); + u3l_log("apply: %d, %x", pag_w, _ce_mug_page(buf_y)); #endif } } @@ -836,7 +831,7 @@ _ce_loom_protect_north(c3_w pgs_w, c3_w old_w) c3_w dif_w = 0; if ( pgs_w ) { - if ( 0 != mprotect((void*)u3_Loom, _ce_pag_y(pgs_w), PROT_READ) ) { + if ( 0 != mprotect(_ce_ptr(0), _ce_len(pgs_w), PROT_READ) ) { fprintf(stderr, "loom: pure north (%u pages): %s\r\n", pgs_w, strerror(errno)); c3_assert(0); @@ -846,8 +841,8 @@ _ce_loom_protect_north(c3_w pgs_w, c3_w old_w) if ( old_w > pgs_w ) { dif_w = old_w - pgs_w; - if ( 0 != mprotect((void*)(u3_Loom + _ce_pag_w(pgs_w)), - _ce_pag_y(dif_w), + if ( 0 != mprotect(_ce_ptr(pgs_w), + _ce_len(dif_w), (PROT_READ | PROT_WRITE)) ) { fprintf(stderr, "loom: foul north (%u pages, %u old): %s\r\n", @@ -878,8 +873,8 @@ _ce_loom_protect_south(c3_w pgs_w, c3_w old_w) c3_w dif_w = 0; if ( pgs_w ) { - if ( 0 != mprotect((void*)(u3_Loom + _ce_pag_w(u3P.pag_w - pgs_w)), - _ce_pag_y(pgs_w), + if ( 0 != mprotect(_ce_ptr(u3P.pag_w - pgs_w), + _ce_len(pgs_w), PROT_READ) ) { fprintf(stderr, "loom: pure south (%u pages): %s\r\n", @@ -892,8 +887,8 @@ _ce_loom_protect_south(c3_w pgs_w, c3_w old_w) c3_w off_w = u3P.pag_w - old_w; dif_w = old_w - pgs_w; - if ( 0 != mprotect((void*)(u3_Loom + _ce_pag_w(off_w)), - _ce_pag_y(dif_w), + if ( 0 != mprotect(_ce_ptr(off_w), + _ce_len(dif_w), (PROT_READ | PROT_WRITE)) ) { fprintf(stderr, "loom: foul south (%u pages, %u old): %s\r\n", @@ -930,8 +925,8 @@ _ce_loom_mapf_north(c3_i fid_i, c3_w pgs_w, c3_w old_w) c3_w dif_w = 0; if ( pgs_w ) { - if ( MAP_FAILED == mmap((void*)u3_Loom, - _ce_pag_y(pgs_w), + if ( MAP_FAILED == mmap(_ce_ptr(0), + _ce_len(pgs_w), PROT_READ, (MAP_FIXED | MAP_PRIVATE), fid_i, 0) ) @@ -945,8 +940,8 @@ _ce_loom_mapf_north(c3_i fid_i, c3_w pgs_w, c3_w old_w) if ( old_w > pgs_w ) { dif_w = old_w - pgs_w; - if ( MAP_FAILED == mmap((void*)(u3_Loom + _ce_pag_w(pgs_w)), - _ce_pag_y(dif_w), + if ( MAP_FAILED == mmap(_ce_ptr(pgs_w), + _ce_len(dif_w), (PROT_READ | PROT_WRITE), (MAP_ANON | MAP_FIXED | MAP_PRIVATE), -1, 0) ) @@ -976,19 +971,14 @@ _ce_loom_mapf_north(c3_i fid_i, c3_w pgs_w, c3_w old_w) static void _ce_loom_blit_north(c3_i fid_i, c3_w pgs_w) { - // fprintf(stderr, "loom: blit north %u\r\n", pgs_w); c3_w i_w; - c3_w* ptr_w; - c3_z off_z; + void* ptr_v; c3_zs ret_zs; for ( i_w = 0; i_w < pgs_w; i_w++ ) { - off_z = _ce_pag_y(i_w); - ptr_w = u3_Loom + _ce_pag_w(i_w); + ptr_v = _ce_ptr(i_w); - if ( _ce_pag_y(1) != - (ret_zs = pread(fid_i, ptr_w, _ce_pag_y(1), off_z)) ) - { + if ( _ce_page != (ret_zs = pread(fid_i, ptr_v, _ce_page, _ce_len(i_w))) ) { if ( 0 < ret_zs ) { fprintf(stderr, "loom: blit north partial read: %"PRIc3_zs"\r\n", ret_zs); @@ -1008,19 +998,14 @@ _ce_loom_blit_north(c3_i fid_i, c3_w pgs_w) static void _ce_loom_blit_south(c3_i fid_i, c3_w pgs_w) { - // fprintf(stderr, "loom: blit south %u\r\n", pgs_w); c3_w i_w; - c3_w* ptr_w; - c3_z off_z; + void* ptr_v; c3_zs ret_zs; for ( i_w = 0; i_w < pgs_w; i_w++ ) { - off_z = _ce_pag_y(i_w); - ptr_w = u3_Loom + _ce_pag_w(u3P.pag_w - (i_w + 1)); + ptr_v = _ce_ptr(u3P.pag_w - (i_w + 1)); - if ( _ce_pag_y(1) != - (ret_zs = pread(fid_i, ptr_w, _ce_pag_y(1), off_z)) ) - { + if ( _ce_page != (ret_zs = pread(fid_i, ptr_v, _ce_page, _ce_len(i_w))) ) { if ( 0 < ret_zs ) { fprintf(stderr, "loom: blit south partial read: %"PRIc3_zs"\r\n", ret_zs); @@ -1045,7 +1030,7 @@ _ce_image_fine(u3e_image* img_u, { ssize_t ret_i; c3_w i_w; - c3_w buf_w[_ce_pag_w(1)]; + c3_y buf_y[_ce_page]; if ( -1 == lseek(img_u->fid_i, 0, SEEK_SET) ) { fprintf(stderr, "loom: image fine seek 0: %s\r\n", strerror(errno)); @@ -1055,7 +1040,7 @@ _ce_image_fine(u3e_image* img_u, for ( i_w=0; i_w < img_u->pgs_w; i_w++ ) { c3_w mem_w, fil_w; - if ( _ce_pag_y(1) != (ret_i = read(img_u->fid_i, buf_w, _ce_pag_y(1))) ) { + if ( _ce_page != (ret_i = read(img_u->fid_i, buf_y, _ce_page)) ) { if ( 0 < ret_i ) { fprintf(stderr, "loom: image (%s) fine partial read: %zu\r\n", img_u->nam_c, (size_t)ret_i); @@ -1066,8 +1051,8 @@ _ce_image_fine(u3e_image* img_u, } c3_assert(0); } - mem_w = u3r_mug_words(ptr_w, _ce_pag_w(1)); - fil_w = u3r_mug_words(buf_w, _ce_pag_w(1)); + mem_w = _ce_mug_page(ptr_w); + fil_w = _ce_mug_page(buf_y); if ( mem_w != fil_w ) { c3_w pag_w = (ptr_w - u3_Loom) >> u3a_page; @@ -1112,10 +1097,10 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) // copy pages into destination image // for ( i_w = 0; i_w < fom_u->pgs_w; i_w++ ) { - c3_w mem_w[_ce_pag_w(1)]; + c3_y buf_y[_ce_page]; c3_w off_w = i_w; - if ( _ce_pag_y(1) != (ret_i = read(fom_u->fid_i, mem_w, _ce_pag_y(1))) ) { + if ( _ce_page != (ret_i = read(fom_u->fid_i, buf_y, _ce_page)) ) { if ( 0 < ret_i ) { fprintf(stderr, "loom: image (%s) copy partial read: %zu\r\n", fom_u->nam_c, (size_t)ret_i); @@ -1127,12 +1112,12 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) return c3n; } else { - if ( -1 == lseek(tou_u->fid_i, _ce_pag_y(off_w), SEEK_SET) ) { + if ( -1 == lseek(tou_u->fid_i, _ce_len(off_w), SEEK_SET) ) { fprintf(stderr, "loom: image (%s) copy seek: %s\r\n", tou_u->nam_c, strerror(errno)); return c3n; } - if ( _ce_pag_y(1) != (ret_i = write(tou_u->fid_i, mem_w, _ce_pag_y(1))) ) { + if ( _ce_page != (ret_i = write(tou_u->fid_i, buf_y, _ce_page)) ) { if ( 0 < ret_i ) { fprintf(stderr, "loom: image (%s) copy partial write: %zu\r\n", tou_u->nam_c, (size_t)ret_i); @@ -1234,7 +1219,7 @@ u3e_save(u3_post low_p, u3_post hig_p) { c3_w nop_w = (low_p >> u3a_page); - c3_w nor_w = (low_p + (_ce_pag_w(1) - 1)) >> u3a_page; + c3_w nor_w = (low_p + (_ce_len_words(1) - 1)) >> u3a_page; c3_w sop_w = hig_p >> u3a_page; c3_assert( (u3P.gar_w > nop_w) && (u3P.gar_w < sop_w) ); @@ -1261,11 +1246,11 @@ u3e_save(u3_post low_p, u3_post hig_p) { _ce_image_fine(&u3P.nor_u, u3_Loom, - _ce_pag_w(1)); + _ce_len_words(1)); _ce_image_fine(&u3P.sou_u, - (u3_Loom + u3C.wor_i) - _ce_pag_w(1), - -(ssize_t)_ce_pag_w(1)); + (u3_Loom + u3C.wor_i) - _ce_len_words(1), + -(ssize_t)_ce_len_words(1)); c3_assert(u3P.nor_u.pgs_w == u3K.nor_w); c3_assert(u3P.sou_u.pgs_w == u3K.sou_w); @@ -1287,12 +1272,12 @@ u3e_save(u3_post low_p, u3_post hig_p) _ce_loom_protect_south(u3P.sou_u.pgs_w, sod_w); { - c3_w* ptr_w = u3_Loom + _ce_pag_w(u3P.nor_u.pgs_w); - c3_w len_w = u3P.pag_w - (u3P.nor_u.pgs_w + u3P.sou_u.pgs_w); + c3_w* ptr_w = _ce_ptr(u3P.nor_u.pgs_w); + c3_z len_z = _ce_len(u3P.pag_w - (u3P.nor_u.pgs_w + u3P.sou_u.pgs_w)); - if ( -1 == madvise((void*)ptr_w, _ce_pag_y(len_w), MADV_DONTNEED) ) { - fprintf(stderr, "loom: madvise() failed for %u pages at %p: %s\r\n", - len_w, ptr_w, strerror(errno)); + if ( -1 == madvise((void*)ptr_w, len_z, MADV_DONTNEED) ) { + fprintf(stderr, "loom: madvise() failed for %zu pages at %p: %s\r\n", + len_z, ptr_w, strerror(errno)); } } @@ -1309,7 +1294,7 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) { size_t sys_i = sysconf(_SC_PAGESIZE); - if ( _ce_pag_y(1) % sys_i ) { + if ( _ce_page % sys_i ) { fprintf(stderr, "loom: incompatible system page size (%zuKB)\r\n", sys_i >> 10); exit(1); @@ -1387,7 +1372,7 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) nuu_o = c3y; } else if ( u3C.wag_w & u3o_no_demand ) { - u3a_print_memory(stderr, "live: loaded", _ce_pag_w(nor_w + sou_w)); + u3a_print_memory(stderr, "live: loaded", _ce_len_words(nor_w + sou_w)); } else { u3a_print_memory(stderr, "live: mapped", nor_w << u3a_page); @@ -1410,8 +1395,8 @@ u3e_yolo(void) { // NB: u3e_save() will reinstate protection flags // - if ( 0 != mprotect((void *)u3_Loom, - u3C.wor_i << 2, + if ( 0 != mprotect(_ce_ptr(0), + _ce_len(u3P.pag_w), (PROT_READ | PROT_WRITE)) ) { // XX confirm recoverable errors From 2f08e4be7da1c5bbc361b2522d9d12bf7d01b331 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 12 Apr 2023 18:44:55 -0400 Subject: [PATCH 19/28] u3: fixes bounds calculation in u3e_check() --- pkg/noun/events.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 536c279f1a..cefa19d589 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -144,15 +144,14 @@ u3e_check(c3_c* cap_c) c3_w sou_w = 0; { - c3_w nwr_w, swu_w; + u3_post low_p, hig_p; + u3m_water(&low_p, &hig_p); - u3m_water(&nwr_w, &swu_w); - - nor_w = (nwr_w + (_ce_len_words(1) - 1)) >> u3a_page; - sou_w = (swu_w + (_ce_len_words(1) - 1)) >> u3a_page; + nor_w = (low_p + (_ce_len_words(1) - 1)) >> u3a_page; + sou_w = u3P.pag_w - (hig_p >> u3a_page); } - /* Count dirty pages. + /* compute checksum over active pages. */ { c3_w i_w, sum_w, mug_w; From 3584270ddce73d07e2e9c4e1637d99b279fef9c8 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 12 Apr 2023 18:47:11 -0400 Subject: [PATCH 20/28] u3: corrects madvice failure printf --- pkg/noun/events.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index cefa19d589..09a034b015 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1271,12 +1271,12 @@ u3e_save(u3_post low_p, u3_post hig_p) _ce_loom_protect_south(u3P.sou_u.pgs_w, sod_w); { - c3_w* ptr_w = _ce_ptr(u3P.nor_u.pgs_w); - c3_z len_z = _ce_len(u3P.pag_w - (u3P.nor_u.pgs_w + u3P.sou_u.pgs_w)); + void* ptr_v = _ce_ptr(u3P.nor_u.pgs_w); + c3_w pgs_w = u3P.pag_w - (u3P.nor_u.pgs_w + u3P.sou_u.pgs_w); - if ( -1 == madvise((void*)ptr_w, len_z, MADV_DONTNEED) ) { - fprintf(stderr, "loom: madvise() failed for %zu pages at %p: %s\r\n", - len_z, ptr_w, strerror(errno)); + if ( -1 == madvise((void*)ptr_v, _ce_len(pgs_w), MADV_DONTNEED) ) { + fprintf(stderr, "loom: madvise() failed for %u pages at %p: %s\r\n", + pgs_w, ptr_v, strerror(errno)); } } From c9014c26790eb7a558545adb94bc92d47c72dd91 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 12 Apr 2023 19:01:18 -0400 Subject: [PATCH 21/28] u3: adds bitmap invariants to snapshot-validation mode --- pkg/noun/events.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 09a034b015..ae67bec176 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -778,6 +778,53 @@ _ce_patch_apply(u3_ce_patch* pat_u) } } +/* _ce_loom_track_sane(): quiescent page state invariants. +*/ +static c3_o +_ce_loom_track_sane(void) +{ + c3_w blk_w, bit_w, max_w, i_w = 0; + c3_o san_o = c3y; + + max_w = u3P.nor_u.pgs_w; + + for ( ; i_w < max_w; i_w++ ) { + blk_w = i_w >> 5; + bit_w = i_w & 31; + + if ( u3P.dit_w[blk_w] & (1 << bit_w) ) { + fprintf(stderr, "loom: insane north %u\r\n", i_w); + san_o = c3n; + } + } + + max_w = u3P.pag_w - u3P.sou_u.pgs_w; + + for ( ; i_w < max_w; i_w++ ) { + blk_w = i_w >> 5; + bit_w = i_w & 31; + + if ( !(u3P.dit_w[blk_w] & (1 << bit_w)) ) { + fprintf(stderr, "loom: insane open %u\r\n", i_w); + san_o = c3n; + } + } + + max_w = u3P.pag_w; + + for ( ; i_w < max_w; i_w++ ) { + blk_w = i_w >> 5; + bit_w = i_w & 31; + + if ( u3P.dit_w[blk_w] & (1 << bit_w) ) { + fprintf(stderr, "loom: insane south %u\r\n", i_w); + san_o = c3n; + } + } + + return san_o; +} + /* _ce_loom_track_north(): [pgs_w] clean, followed by [dif_w] dirty. */ void @@ -1270,6 +1317,10 @@ u3e_save(u3_post low_p, u3_post hig_p) _ce_loom_protect_south(u3P.sou_u.pgs_w, sod_w); +#ifdef U3_SNAPSHOT_VALIDATION + c3_assert( c3y == _ce_loom_track_sane() ); +#endif + { void* ptr_v = _ce_ptr(u3P.nor_u.pgs_w); c3_w pgs_w = u3P.pag_w - (u3P.nor_u.pgs_w + u3P.sou_u.pgs_w); From 127a805d2493f7ebe51994f818d5f0cdc268e4bd Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 12 Apr 2023 20:05:36 -0400 Subject: [PATCH 22/28] u3: adds pre-patch-application snapshot validation --- pkg/noun/events.c | 132 +++++++++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 55 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index ae67bec176..6864a8c657 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1067,53 +1067,72 @@ _ce_loom_blit_south(c3_i fid_i, c3_w pgs_w) } #ifdef U3_SNAPSHOT_VALIDATION -/* _ce_image_fine(): compare image to memory. +/* _ce_page_fine(): compare page in memory and on disk. */ -static void -_ce_image_fine(u3e_image* img_u, - c3_w* ptr_w, - c3_ws stp_ws) +static c3_o +_ce_page_fine(u3e_image* img_u, c3_w pag_w, c3_z off_z) { ssize_t ret_i; - c3_w i_w; c3_y buf_y[_ce_page]; - if ( -1 == lseek(img_u->fid_i, 0, SEEK_SET) ) { - fprintf(stderr, "loom: image fine seek 0: %s\r\n", strerror(errno)); + if ( _ce_page != + (ret_i = pread(img_u->fid_i, buf_y, _ce_page, off_z)) ) + { + if ( 0 < ret_i ) { + fprintf(stderr, "loom: image (%s) fine partial read: %zu\r\n", + img_u->nam_c, (size_t)ret_i); + } + else { + fprintf(stderr, "loom: image (%s) fine read: %s\r\n", + img_u->nam_c, strerror(errno)); + } c3_assert(0); } - for ( i_w=0; i_w < img_u->pgs_w; i_w++ ) { - c3_w mem_w, fil_w; + { + c3_w mug_w = _ce_mug_page(_ce_ptr(pag_w)); + c3_w fug_w = _ce_mug_page(buf_y); - if ( _ce_page != (ret_i = read(img_u->fid_i, buf_y, _ce_page)) ) { - if ( 0 < ret_i ) { - fprintf(stderr, "loom: image (%s) fine partial read: %zu\r\n", - img_u->nam_c, (size_t)ret_i); - } - else { - fprintf(stderr, "loom: image (%s) fine read: %s\r\n", - img_u->nam_c, strerror(errno)); - } - c3_assert(0); + if ( mug_w != fug_w ) { + fprintf(stderr, "loom: image (%s) mismatch: " + "page %d, mem_w %x, fil_w %x, K %x\r\n", + img_u->nam_c, pag_w, mug_w, fug_w, u3K.mug_w[pag_w]); + return c3n; } - mem_w = _ce_mug_page(ptr_w); - fil_w = _ce_mug_page(buf_y); + } - if ( mem_w != fil_w ) { - c3_w pag_w = (ptr_w - u3_Loom) >> u3a_page; + return c3y; +} - fprintf(stderr, "loom: image (%s) mismatch: " - "page %d, mem_w %x, fil_w %x, K %x\r\n", - img_u->nam_c, - pag_w, - mem_w, - fil_w, - u3K.mug_w[pag_w]); - abort(); +/* _ce_loom_fine(): compare clean pages in memory and on disk. +*/ +static c3_o +_ce_loom_fine(void) +{ + c3_w blk_w, bit_w, pag_w, i_w; + c3_o fin_o = c3y; + + for ( i_w = 0; i_w < u3P.nor_u.pgs_w; i_w++ ) { + pag_w = i_w; + blk_w = pag_w >> 5; + bit_w = pag_w & 31; + + if ( !(u3P.dit_w[blk_w] & (1 << bit_w)) ) { + fin_o = c3a(fin_o, _ce_page_fine(&u3P.nor_u, pag_w, _ce_len(pag_w))); + } + } + + for ( i_w = 0; i_w < u3P.sou_u.pgs_w; i_w++ ) { + pag_w = u3P.pag_w - (i_w + 1); + blk_w = pag_w >> 5; + bit_w = pag_w & 31; + + if ( !(u3P.dit_w[blk_w] & (1 << bit_w)) ) { + fin_o = c3a(fin_o, _ce_page_fine(&u3P.sou_u, pag_w, _ce_len(i_w))); } - ptr_w += stp_ws; } + + return fin_o; } #endif @@ -1275,7 +1294,8 @@ u3e_save(u3_post low_p, u3_post hig_p) } } - /* attempt to avoid propagating anything insane to disk */ + // attempt to avoid propagating anything insane to disk + // u3a_loom_sane(); // u3a_print_memory(stderr, "sync: save", 4096 * pat_u->con_u->pgs_w); @@ -1286,46 +1306,48 @@ u3e_save(u3_post low_p, u3_post hig_p) c3_assert(!"loom: save failed"); } - _ce_patch_apply(pat_u); - #ifdef U3_SNAPSHOT_VALIDATION - { - _ce_image_fine(&u3P.nor_u, - u3_Loom, - _ce_len_words(1)); - - _ce_image_fine(&u3P.sou_u, - (u3_Loom + u3C.wor_i) - _ce_len_words(1), - -(ssize_t)_ce_len_words(1)); - - c3_assert(u3P.nor_u.pgs_w == u3K.nor_w); - c3_assert(u3P.sou_u.pgs_w == u3K.sou_w); - } + // check that clean pages are correct + // + c3_assert( c3y == _ce_loom_fine() ); #endif + _ce_patch_apply(pat_u); + _ce_image_sync(&u3P.nor_u); _ce_image_sync(&u3P.sou_u); _ce_patch_free(pat_u); _ce_patch_delete(); + _ce_loom_protect_south(u3P.sou_u.pgs_w, sod_w); + +#ifdef U3_SNAPSHOT_VALIDATION + // check that all pages in the north/south segments are clean, + // all between are dirty, and clean pages are *fine* + // + // since total finery requires total cleanliness, + // pages of the north segment are protected twice. + // + _ce_loom_protect_north(u3P.nor_u.pgs_w, nod_w); + + c3_assert( c3y == _ce_loom_track_sane() ); + c3_assert( c3y == _ce_loom_fine() ); +#endif + if ( u3C.wag_w & u3o_no_demand ) { +#ifndef U3_SNAPSHOT_VALIDATION _ce_loom_protect_north(u3P.nor_u.pgs_w, nod_w); +#endif } else { _ce_loom_mapf_north(u3P.nor_u.fid_i, u3P.nor_u.pgs_w, nod_w); } - _ce_loom_protect_south(u3P.sou_u.pgs_w, sod_w); - -#ifdef U3_SNAPSHOT_VALIDATION - c3_assert( c3y == _ce_loom_track_sane() ); -#endif - { void* ptr_v = _ce_ptr(u3P.nor_u.pgs_w); c3_w pgs_w = u3P.pag_w - (u3P.nor_u.pgs_w + u3P.sou_u.pgs_w); - if ( -1 == madvise((void*)ptr_v, _ce_len(pgs_w), MADV_DONTNEED) ) { + if ( -1 == madvise(ptr_v, _ce_len(pgs_w), MADV_DONTNEED) ) { fprintf(stderr, "loom: madvise() failed for %u pages at %p: %s\r\n", pgs_w, ptr_v, strerror(errno)); } From 381353851633f30fc05ad1435f4c329b9cc73e50 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 12 Apr 2023 20:07:20 -0400 Subject: [PATCH 23/28] u3: print snapshot update size under -v --- pkg/noun/events.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 6864a8c657..7819ff7d11 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1298,7 +1298,9 @@ u3e_save(u3_post low_p, u3_post hig_p) // u3a_loom_sane(); - // u3a_print_memory(stderr, "sync: save", 4096 * pat_u->con_u->pgs_w); + if ( u3C.wag_w & u3o_verbose ) { + u3a_print_memory(stderr, "sync: save", pat_u->con_u->pgs_w << u3a_page); + } _ce_patch_sync(pat_u); From 294079293388d5952b6c49857bd48d2eed24eeb9 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 12 Apr 2023 23:46:48 -0400 Subject: [PATCH 24/28] u3: stat images after patch application under snapshot validation --- pkg/noun/events.c | 74 +++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 7819ff7d11..f43d95b7c0 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -279,6 +279,41 @@ u3e_fault(u3_post low_p, u3_post hig_p, u3_post off_p) return u3e_flaw_good; } +/* _ce_image_stat(): measure image. +*/ +static c3_o +_ce_image_stat(u3e_image* img_u, c3_w* pgs_w) +{ + struct stat buf_u; + + if ( -1 == fstat(img_u->fid_i, &buf_u) ) { + fprintf(stderr, "loom: stat %s: %s\r\n", img_u->nam_c, strerror(errno)); + c3_assert(0); + return c3n; + } + else { + c3_z siz_z = buf_u.st_size; + c3_z pgs_z = (siz_z + (_ce_page - 1)) >> (u3a_page + 2); + + if ( !siz_z ) { + *pgs_w = 0; + return c3y; + } + else if ( siz_z != _ce_len(pgs_z) ) { + fprintf(stderr, "loom: %s corrupt size %zu\r\n", img_u->nam_c, siz_z); + return c3n; + } + else if ( pgs_z > UINT32_MAX ) { + fprintf(stderr, "loom: %s overflow %zu\r\n", img_u->nam_c, siz_z); + return c3n; + } + else { + *pgs_w = (c3_w)pgs_z; + return c3y; + } + } +} + /* _ce_image_open(): open or create image. */ static c3_o @@ -301,32 +336,11 @@ _ce_image_open(u3e_image* img_u) fprintf(stderr, "loom: c3_open %s: %s\r\n", ful_c, strerror(errno)); return c3n; } + else if ( c3n == _ce_image_stat(img_u, &img_u->pgs_w) ) { + return c3n; + } else { - struct stat buf_u; - - if ( -1 == fstat(img_u->fid_i, &buf_u) ) { - fprintf(stderr, "loom: stat %s: %s\r\n", ful_c, strerror(errno)); - c3_assert(0); - return c3n; - } - else { - c3_z siz_z = buf_u.st_size; - c3_z pgs_z = (siz_z + (_ce_page - 1)) >> (u3a_page + 2); - - if ( !siz_z ) { - return c3y; - } - else { - if ( siz_z != _ce_len(pgs_z) ) { - fprintf(stderr, "%s: corrupt size %zu\r\n", ful_c, siz_z); - return c3n; - } - img_u->pgs_w = (c3_w)pgs_z; - c3_assert( pgs_z == (c3_z)img_u->pgs_w ); - - return c3y; - } - } + return c3y; } } @@ -1321,6 +1335,16 @@ u3e_save(u3_post low_p, u3_post hig_p) _ce_patch_free(pat_u); _ce_patch_delete(); +#ifdef U3_SNAPSHOT_VALIDATION + { + c3_w pgs_w; + c3_assert( c3y == _ce_image_stat(&u3P.nor_u, &pgs_w) ); + c3_assert( pgs_w == u3P.nor_u.pgs_w ); + c3_assert( c3y == _ce_image_stat(&u3P.sou_u, &pgs_w) ); + c3_assert( pgs_w == u3P.sou_u.pgs_w ); + } +#endif + _ce_loom_protect_south(u3P.sou_u.pgs_w, sod_w); #ifdef U3_SNAPSHOT_VALIDATION From fa2af3dc9110c9c8675e9b4342856098ec126113 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 12 Apr 2023 23:55:13 -0400 Subject: [PATCH 25/28] u3: check for corrupt snapshot/size after restoration --- pkg/noun/manage.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index 51bc0bea79..996565b26c 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -597,13 +597,32 @@ _find_home(void) c3_w* mem_w = u3_Loom + u3C.walign_w; c3_w siz_w = c3_wiseof(u3v_home); c3_w len_w = u3C.wor_i - u3C.walign_w; - c3_w* mat_w = c3_align(mem_w + len_w - siz_w, u3C.balign_d, C3_ALGLO); + c3_w* mat_w = c3_align(mem_w + len_w - siz_w, u3C.balign_d, C3_ALGLO); u3H = (void *)mat_w; u3R = &u3H->rod_u; - // this looks risky, but there are no legitimate scenarios where it's wrong - u3R->cap_p = u3R->mat_p = u3C.wor_i - c3_wiseof(*u3H); + // this looks risky, but there are no legitimate scenarios + // where it's wrong + // + u3R->cap_p = u3R->mat_p = u3a_outa(u3H); + + // check for obvious corruption + // + { + c3_w nor_w, sou_w; + u3_post low_p, hig_p; + u3m_water(&low_p, &hig_p); + + nor_w = (low_p + ((1 << u3a_page) - 1)) >> u3a_page; + sou_w = u3P.pag_w - (hig_p >> u3a_page); + + if ( (nor_w != u3P.nor_u.pgs_w) || (sou_w != u3P.sou_u.pgs_w) ) { + fprintf(stderr, "loom: corrupt size north (%u, %u) south (%u, %u)\r\n", + nor_w, u3P.nor_u.pgs_w, sou_w, u3P.sou_u.pgs_w); + c3_assert(!"loom: corrupt size"); + } + } /* As a further guard against any sneaky loom corruption */ u3a_loom_sane(); From bfcf4130414192e8ecb985122ef3d5f2b3e972da Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 10 May 2023 15:23:57 -0400 Subject: [PATCH 26/28] tests: use u3m_boot_lite() instead of manual init --- pkg/noun/nock_tests.c | 4 +--- pkg/noun/serial_tests.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/pkg/noun/nock_tests.c b/pkg/noun/nock_tests.c index 9228416faf..8d4a7d23dc 100644 --- a/pkg/noun/nock_tests.c +++ b/pkg/noun/nock_tests.c @@ -7,9 +7,7 @@ static void _setup(void) { - u3m_init(1 << 24); - u3m_pave(c3y); - u3e_init(); + u3m_boot_lite(1 << 24); } static u3_noun diff --git a/pkg/noun/serial_tests.c b/pkg/noun/serial_tests.c index 7a57ddc0b2..5f1caf7075 100644 --- a/pkg/noun/serial_tests.c +++ b/pkg/noun/serial_tests.c @@ -7,9 +7,7 @@ static void _setup(void) { - u3m_init(1 << 24); - u3m_pave(c3y); - u3e_init(); + u3m_boot_lite(1 << 24); } static void From cfb037763a2a4461de594e0e330d83b7f5d919d7 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 18 May 2023 15:40:45 -0400 Subject: [PATCH 27/28] u3: correct buffer type in _ce_patch_apply() --- pkg/noun/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index cfe35d242e..79f3ed1143 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -749,7 +749,7 @@ _ce_patch_apply(u3_ce_patch* pat_u) // for ( i_w = 0; i_w < pat_u->con_u->pgs_w; i_w++ ) { c3_w pag_w = pat_u->con_u->mem_u[i_w].pag_w; - c3_w buf_y[_ce_page]; + c3_y buf_y[_ce_page]; c3_i fid_i; c3_z off_z; From 6760d5db8c6448edb5f3497a577412bb18c10836 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 18 May 2023 15:57:09 -0400 Subject: [PATCH 28/28] vere: support --no-demand in all commands with --loom --- pkg/vere/main.c | 80 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/pkg/vere/main.c b/pkg/vere/main.c index fe8c038019..799bd753b2 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -1459,7 +1459,8 @@ _cw_info(c3_i argc, c3_c* argv[]) c3_w arg_w; static struct option lop_u[] = { - { "loom", required_argument, NULL, c3__loom }, + { "loom", required_argument, NULL, c3__loom }, + { "no-demand", no_argument, NULL, 6 }, { NULL, 0, NULL, 0 } }; @@ -1473,6 +1474,11 @@ _cw_info(c3_i argc, c3_c* argv[]) } } break; + case 6: { // no-demand + u3_Host.ops_u.map = c3n; + u3C.wag_w |= u3o_no_demand; + } break; + case '?': { fprintf(stderr, "invalid argument\r\n"); exit(1); @@ -1522,7 +1528,8 @@ _cw_grab(c3_i argc, c3_c* argv[]) c3_w arg_w; static struct option lop_u[] = { - { "loom", required_argument, NULL, c3__loom }, + { "loom", required_argument, NULL, c3__loom }, + { "no-demand", no_argument, NULL, 6 }, { NULL, 0, NULL, 0 } }; @@ -1536,6 +1543,11 @@ _cw_grab(c3_i argc, c3_c* argv[]) } } break; + case 6: { // no-demand + u3_Host.ops_u.map = c3n; + u3C.wag_w |= u3o_no_demand; + } break; + case '?': { fprintf(stderr, "invalid argument\r\n"); exit(1); @@ -1577,7 +1589,8 @@ _cw_cram(c3_i argc, c3_c* argv[]) c3_w arg_w; static struct option lop_u[] = { - { "loom", required_argument, NULL, c3__loom }, + { "loom", required_argument, NULL, c3__loom }, + { "no-demand", no_argument, NULL, 6 }, { NULL, 0, NULL, 0 } }; @@ -1591,6 +1604,11 @@ _cw_cram(c3_i argc, c3_c* argv[]) } } break; + case 6: { // no-demand + u3_Host.ops_u.map = c3n; + u3C.wag_w |= u3o_no_demand; + } break; + case '?': { fprintf(stderr, "invalid argument\r\n"); exit(1); @@ -1654,6 +1672,7 @@ _cw_queu(c3_i argc, c3_c* argv[]) static struct option lop_u[] = { { "loom", required_argument, NULL, c3__loom }, + { "no-demand", no_argument, NULL, 6 }, { "replay-from", required_argument, NULL, 'r' }, { NULL, 0, NULL, 0 } }; @@ -1668,6 +1687,11 @@ _cw_queu(c3_i argc, c3_c* argv[]) } } break; + case 6: { // no-demand + u3_Host.ops_u.map = c3n; + u3C.wag_w |= u3o_no_demand; + } break; + case 'r': { roc_c = strdup(optarg); } break; @@ -1742,7 +1766,8 @@ _cw_meld(c3_i argc, c3_c* argv[]) c3_w arg_w; static struct option lop_u[] = { - { "loom", required_argument, NULL, c3__loom }, + { "loom", required_argument, NULL, c3__loom }, + { "no-demand", no_argument, NULL, 6 }, { NULL, 0, NULL, 0 } }; @@ -1756,6 +1781,11 @@ _cw_meld(c3_i argc, c3_c* argv[]) } } break; + case 6: { // no-demand + u3_Host.ops_u.map = c3n; + u3C.wag_w |= u3o_no_demand; + } break; + case '?': { fprintf(stderr, "invalid argument\r\n"); exit(1); @@ -1807,8 +1837,9 @@ _cw_next(c3_i argc, c3_c* argv[]) c3_w arg_w; static struct option lop_u[] = { - { "arch", required_argument, NULL, 'a' }, - { "loom", required_argument, NULL, c3__loom }, + { "arch", required_argument, NULL, 'a' }, + { "loom", required_argument, NULL, c3__loom }, + { "no-demand", no_argument, NULL, 6 }, { NULL, 0, NULL, 0 } }; @@ -1826,6 +1857,11 @@ _cw_next(c3_i argc, c3_c* argv[]) } } break; + case 6: { // no-demand + u3_Host.ops_u.map = c3n; + u3C.wag_w |= u3o_no_demand; + } break; + case '?': { fprintf(stderr, "invalid argument\r\n"); exit(1); @@ -1867,7 +1903,8 @@ _cw_pack(c3_i argc, c3_c* argv[]) c3_w arg_w; static struct option lop_u[] = { - { "loom", required_argument, NULL, c3__loom }, + { "loom", required_argument, NULL, c3__loom }, + { "no-demand", no_argument, NULL, 6 }, { NULL, 0, NULL, 0 } }; @@ -1881,6 +1918,11 @@ _cw_pack(c3_i argc, c3_c* argv[]) } } break; + case 6: { // no-demand + u3_Host.ops_u.map = c3n; + u3C.wag_w |= u3o_no_demand; + } break; + case '?': { fprintf(stderr, "invalid argument\r\n"); exit(1); @@ -1978,7 +2020,8 @@ _cw_prep(c3_i argc, c3_c* argv[]) c3_w arg_w; static struct option lop_u[] = { - { "loom", required_argument, NULL, c3__loom }, + { "loom", required_argument, NULL, c3__loom }, + { "no-demand", no_argument, NULL, 6 }, { NULL, 0, NULL, 0 } }; @@ -1992,6 +2035,11 @@ _cw_prep(c3_i argc, c3_c* argv[]) } } break; + case 6: { // no-demand + u3_Host.ops_u.map = c3n; + u3C.wag_w |= u3o_no_demand; + } break; + case '?': { fprintf(stderr, "invalid argument\r\n"); exit(1); @@ -2032,7 +2080,8 @@ _cw_chop(c3_i argc, c3_c* argv[]) c3_w arg_w; static struct option lop_u[] = { - { "loom", required_argument, NULL, c3__loom }, + { "loom", required_argument, NULL, c3__loom }, + { "no-demand", no_argument, NULL, 6 }, { NULL, 0, NULL, 0 } }; @@ -2046,6 +2095,11 @@ _cw_chop(c3_i argc, c3_c* argv[]) } } break; + case 6: { // no-demand + u3_Host.ops_u.map = c3n; + u3C.wag_w |= u3o_no_demand; + } break; + case '?': { fprintf(stderr, "invalid argument\r\n"); exit(1); @@ -2315,7 +2369,8 @@ _cw_vile(c3_i argc, c3_c* argv[]) c3_w arg_w; static struct option lop_u[] = { - { "loom", required_argument, NULL, c3__loom }, + { "loom", required_argument, NULL, c3__loom }, + { "no-demand", no_argument, NULL, 6 }, { NULL, 0, NULL, 0 } }; @@ -2329,6 +2384,11 @@ _cw_vile(c3_i argc, c3_c* argv[]) } } break; + case 6: { // no-demand + u3_Host.ops_u.map = c3n; + u3C.wag_w |= u3o_no_demand; + } break; + case '?': { fprintf(stderr, "invalid argument\r\n"); exit(1);