ramdisk: the live root grows into half of memory

The live root was a fixed 96 MB image in the kernel: 60 MB of zeros on
the ISO, twice, and room for 60 MB of packages whatever the machine had.

Now the image is only what the root holds, plus slack, measured by
building it once large. Past its end the ramdisk goes on to half of the
memory free at mount, as pages taken the first time each block is
written; an unwritten block reads as zeros and costs nothing. SchFS
keeps no free-space map on disk, so growing a volume is a larger total
before open builds the map: grow_to, set for the ramdisk root.

8 GB machine: a 4 GB root, Xorg installed into it in 77 s with 7.6 GB
still free. The ISO is 172 MB instead of 344.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-24 17:20:43 +02:00
commit d0941780f5
7 changed files with 120 additions and 13 deletions

View file

@ -641,6 +641,9 @@ kmount_slot(int slot, uint bdev)
// Opening with a page allocator also builds the allocation bitmap, by walking
// the tree — the only mount-time cost SchFS has, and what buys it a mount
// that cannot disagree with the filesystem it just adopted.
// The live root fills its ramdisk, however much memory that turned out to
// be. See kernel/dev/ramdisk.c.
m->vol.grow_to = (bdev == RAMDISK_DEV) ? ramdisk_blocks() : 0;
int r = schfs_vol_open(&m->vol, &bd, &cx, kd_palloc, kd_pfree);
if (r == -1)
return -EINVAL; /* not a SchFS volume at all */

View file

@ -104,6 +104,13 @@ struct schfs_vol {
uint64_t total_blocks;
uint64_t free_blocks;
// Set by the opener before schfs_vol_open: the device's size, when the
// volume should grow to fill it. Nothing on disk records which blocks are
// free -- open rebuilds that from the tree -- so growing is only a larger
// total before the map is built, and the next commit writes it down. The
// live root uses it to fill a ramdisk sized from memory at boot. 0, and
// anything not larger than the volume, leaves it alone.
uint64_t grow_to;
uint64_t next_objectid;
uint64_t root_objectid;
uint64_t generation; // last *committed* transaction group

View file

@ -215,6 +215,8 @@ schfs_vol_open(struct schfs_vol *v, struct schfs_bdev *dev,
}
vol_from_uber(v, u, best_slot);
if (v->grow_to > v->total_blocks)
v->total_blocks = v->grow_to;
v->readonly = 1; // until an allocation map exists, below
if (v->dev.bread(v->dev.ctx, v->tree.root, x->a) != 0)