system: mount SD cards async with bounded dirty-page writeback - #1535
system: mount SD cards async with bounded dirty-page writeback#1535WLTB-Gino wants to merge 1 commit into
Conversation
Mounting with -o sync serializes every write: each write(2) blocks until the card acks, so card-internal GC pauses (100ms-1s+) propagate straight into writers - rmr drops frames while recording, timelapse stalls. RAM was bounded by allowing only one write in flight. Drop sync from the mdev automount and bound dirty pages globally instead: the flusher starts at 512K dirty and writers are throttled at 4M. RAM is still capped (4M of dirty pages), but writes coalesce and SD stalls are absorbed by the dirty budget instead of stalling the recorder. Since the mount is now async, flush dirty data on umount so a pulled card does not leave up to 4M unwritten. Signed-off-by: WLTB Gino <gino@wltb.local>
|
Thanks for this — the direction is right, but I'm not comfortable merging it as-is. This is a durability change, not a perf change, and it's untested on hardware. Two things need addressing first. 1. This needs before/after hardware test results, not a design argument. Dropping Please provide real hardware results comparing
2. Minor: the sysctl comment is misleading.
Also worth stating in the commit message: the |
|
first test results on a camera running record+audio+timelapse+stream (stress test): Further tests from other users are welcome. I dont have a T31/64MB to test.
Note that the patch increases the total free RAM, as it decreases the existing dirty budget from 8.6MB (20%) to 4MB on jooan a6m, and at the same time improves the reliability and SIGNIFICANTLY decreases the frame loss. win win |
|
Companion work on the streamer side (concept stage, being thought through): gtxaspec/raptor#46. This PR absorbs card GC pauses with a bounded dirty-page budget; the raptor PR targets the other failure surface: power loss and card yank. As the streamer streams video into a recording file, that growing file keeps a FAT sector hot for the entire recording: each time the file grows past its current allocation, the sector holding the FAT chain tail is rewritten (every 4-8KB of growth at 4-8KB clusters), so FAT1+FAT2 metadata writes are sprinkled continuously through the body, and a torn FAT sector is shared - it can crosslink and destroy many files and directories at once. raptor#46 makes rmr record under Honest status: tests written but not executed, no device validation yet. The two PRs are independent layers - how dirty data reaches the card, vs. what filesystem metadata a crash can catch mid-write. |
|
This is relevant also to NFS mount. right now on slow network the whole 20% memory will be used as dirty page cache, potentially causing memory starvation on other services. this change limits the dirty page cache to 4MB, about 10% of memory. Alternatively, if we're ok with 20% dirty page cache for NFS, as it is currently defined, then we should be ok with (same) 20% for sdcard too. Either way, its good to have this number known and purposely chosen to fit thingino system requirements |
|
Following up on @nicolasroche898's question 3 (ratio vs bytes): swept every camera defconfig against the SoC RAM maps to answer "is any supported board's stock 20% ceiling already at or below the pinned 4MB?" No. The stock ratio ceiling bottoms out above 4MB on every supported board:
(Caveat: the 20% is of dirtyable memory, not total Linux RAM, so effective ceilings on a loaded camera run lower and float during runtime — that non-determinism is exactly what the byte pin removes.) So the 4M hard cap is at-or-below stock behavior fleet-wide: a genuine tightening on almost every board, near-neutral only on the A12. |
Problem
SD cards are automounted with
-o sync(/usr/lib/mdev/automount). With a sync mount, everywrite(2)blocks until the SD card acknowledges it — only one write in flight per writer. That keeps RAM pressure down, but it means card-internal GC pauses (100 ms to over a second) propagate directly into whatever is writing: raptor/rmr drops frames while recording, timelapse stalls.Change
syncfrom the automount, keepnoatime— this is the dominant change.syncis far more aggressive than anything else in this PR: zero buffering, every write blocks immediately, every card stall lands directly in the writer./etc/sysctl.conf(applied byS00sysctl):vm.dirty_background_bytes = 512K— flusher wakes early, keeps steady-state dirty memory near zerovm.dirty_bytes = 4M— hard throttle ceiling; the remaining headroom absorbs card stallssyncon umount — with an async mount, the lazy umount could otherwise leave up to 4 MB unflushed when the card is pulled.RAM is still capped — 4 MB of dirty pages replaces "one write in flight" as the bound — but writes coalesce and GC stalls are absorbed by the dirty budget instead of stalling the recorder.
Before / after
Before: sync mount. Zero dirty buffering on the card — writes block on every
write(2), so card GC pauses hit the recorder in full.After: async mount with pinned byte limits. The kernel default would be ratio-based (
dirty_background_ratio = 10/dirty_ratio = 20— ~4.3 MB / ~8.6 MB on a 43 MB board, scaling with RAM); this PR pins deterministic bytes instead so the limits are identical on every board. Compared to the sync mount, the write path is massively looser — up to 4 MB of buffering where before there was none.Testing
Not yet tested on hardware — validation on a real recording workload (raptor/rmr to SD) is pending. Feedback from testers on other SoC families and workloads welcome.