blob: bail-safe blob reads via road-owned hands - #1108
Open
matthew-levan wants to merge 30 commits into
Open
matthew-levan wants to merge 30 commits into
matthew-levan wants to merge 30 commits into
Conversation
…writing the store
…k, one pier, and mars's deletion hook
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Blob reads on
ml/bobwent throughu3_blob_mmap(): an anonymous mapping the caller unmapped by hand, recorded nowhere, so anyu3m_bailor signal that longjmp'd while one was live leaked it. The exposed sites were the hottest:u3_blob_load,u3r_view_padd, paired views incat/aor/shax/argon2, jam across_cs_jam_fib_grow, every loop that allocates under a view. Each mapping also charged the file size against process VA.Road-owned hands (
pkg/noun/blob.c)A
u3_blob_handis an open blob file owned by the road that opened it: fd, file size, cached bit-length, live-view count, optional read-only mapping. Nodes link by pointer.bob_p, a formerfut_wslot inu3a_road(layout and offset asserts unchanged), allocate them in their own heap, deduplicate by blob id, and retain them until the road falls. A trap that reads one blob a thousand times opens it once. A nested road borrows an inner ancestor's hand without listing it.u3_blob_data/u3_blob_data_wid: the file mapped read-only, owned by the hand. Bytes past EOF read as zero through the last page (u3_blob_hand_pad); a wider request reserves anonymous zero pages and fixes the file's pages over their head, so one pointer covers any width. A remap is refused while another live view holds the hand; a file that shrank under the hand is refused rather than mapped. Windows maps exactly the file and has no fixed mappings, so it falls back past the file's pages.u3_blob_drain(rod)/u3_blob_drain_kids(): close every hand held by a road, or by every road below home.EMFILE, an inner road evicts its oldest idle hand and retries; with none idle it bails%file, so a resource condition never reads as a deterministic nock failure. The home road returns 0. Replay maps%fileto a save-and-exit.Unwinding
u3m_falldrains the road it leaves. Every road exits there except by a signal caught at the top, so this replaces the sweep inu3m_bailand the leak check inu3m_soft_top._cm_signal_resetdrains the kid chain before cutting it. All signal-driven unwinds (SIGINT, SIGTERM, SIGVTALRM, stack overflow, loom%meme) land there through the single catch inu3m_soft_top.u3m_crit_enter/u3m_crit_leave: an fd is on a list before a signal can unwind the opener, and a drain finishes unlinking before recovery can drain again. POSIX holds SIGINT/SIGTERM/SIGVTALRM withsigprocmask; the Windowsrsignalemulation records a held signal as pending and delivers it at unblock.u3r_viewis the only way to read a bobu3r_viewis a plain struct,{byt_y, len_w, kin_e, han_u, raw_d}, with two modes over one type:u3r_view_openopens the hand and maps nothing;u3r_view_readcopies any byte range, from the hand's mapping if the road already has one and by pread otherwise, zero-fills past the atom, and returns the count that came from the atom.u3r_view_metgives the full-width bit length. The fixed-width accessors,u3r_sing/u3r_comp,u3r_blob_load/u3r_blob_cut,u3r_met_d(which replacesu3r_blob_metand the bob dispatch inmetand both jam encoders), and the king's http and unix streaming all read this way.ripreads its atom as a word buffer through a flat view and no longer materializes a bob.u3r_view_initandu3r_view_paddalias the hand's mapping, widened to the pad, so a bob pad never allocates. A direct atom's value sits inraw_d; a pad over a loom atom is a loom pad.A view owns nothing. It borrows the loom atom, the hand's mapping, or
raw_d, andu3r_view_donereleases its hold.u3r_view_openis the sole opener: every call on a hand sits inside au3r_view_*function, and outside retrieve.c only blob.c and the tests name one.retrieve.hstates the lifetime rule, the semantics of each mode, and the memory behavior per kind.u3_blob_mmap/u3_blob_umapandu3r_blob_mmap/u3r_blob_umapare removed.Mars is the only writer
u3_blob_move_stgis the one function that createsbob/<mug>/<seq>.u3_blob_stageandu3_blob_stage_fdwrite bytes to.urb/bob/stg/;u3_blob_saveandu3_blob_save_fdare stage-then-install for mars and the tests. The king never calls them: http bodies at or past the threshold and reassembled mesa packets are staged, sent in a%blobwrit, and their%requestor%heeris planned from the install callback, so every king-held bob is leased from the moment it exists. The http request is named by connection and sequence across the wait, since the client may close it first; a refused install answers 500, and a refused packet is dropped for the sender to retransmit. The unix initial scan runs before mars can install anything and reads a large file into the loom; the watcher stages later changes as before.King side
u3_hbodblob chunks are{vue_u, off_d, len_w}sharing one heap-allocated windowed view;_http_hgen_sendreads each chunk into a heap buffer only as h2o asks for it, so a streamed response holds at most twoU3_HTTP_BOB_CHUNKbuffers regardless of blob size. The tail chunk owns the view. A bob whose blob cannot be opened fails the response with a 500 instead of serving zeros._unix_write_file_hardstreams through a view.Bank marking
u3v_markmarked the blob bank HAMT but not the walloc'du3a_blobrecords it points at, sou3a_sweep(|mass, gc, pack) freed every record as a leak and every bob then named a garbage file. The records are marked and reported under "blob bank / records".|massThe king logs
king: blob handles: Non%mass; the serf printsblob handles: Nafter its report (0 between events). Scry-served files never give the king a bob: the range is folded into the scry, arvo slices withcut, and each response is a plain atom.Tests (
blob-test, 54)Hand lifetime; no sharing on the home road; one hand across a thousand open/close pairs on an inner road, released at fall; a grandchild borrowing an inner parent's hand; the retention cap;
EMFILEon the home road and eviction then%fileon an inner road; drains on bail,%memeunder a view, cue bailing under a view,u3m_signal, a real SIGVTALRM while the road's list is churned, a real SIGINT outside and inside a critical section; leaked normal return; home hands surviving inner unwinds; a lone view widening its mapping in place and a second live view forcing the fallback pad; flat pads inside the page, 100000 bytes past it, loom, direct, truncated; windowed views over a bob, a loom atom, and a direct atom, read inside and past the end, never mapping; readers under a live mapping; wipe under a live hand;u3_blob_stop; truncation under an open hand; every entry point against a missing file; window-boundary lengths for met and compare; empty files; staging from a buffer and a descriptor installing to the same blob as a direct save, with a short source refused; 300 concurrent hands; both jam encoders on a multi-window bob byte-identical to the materialized atom;rsh/end/cutagainst the materialized atom; mark+sweep keeping the bank record underu3o_leak_crash. POSIX-only tests compile out on Windows.Follow-ups
u3_blob_save_fdandu3_blob_move_stgstill mmap the staging file to mug and dedup it; streaming them needs an incremental mug.u3_blob_bsink's staging fd is not registered; both callers run on the home road.u3_disk_stakeruns; a fallback base belongs to the Windows loom branch.