system: mkfs work disks with lazy_itable_init + lazy_journal_init

mkfs.ext4 zeroes the entire inode table and journal at format time
unless told otherwise. On an 8 GiB work disk that's roughly 500-700ms
of host CPU/IO per 'banger vm create', for a one-time small per-write
penalty inside the guest the first time it touches an unwritten
inode that nobody can perceive.

Centralise the canonical mkfs -E option list as
system.MkfsExtraOptions and use it everywhere banger calls mkfs.ext4
on a VM-internal image: the no-seed work disk, MaterializeWorkDisk,
BuildWorkSeedImage, and the imagepull rootfs builder. The work-disk
paths feed vm create directly; the others are one-off but still
benefit from the faster format.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Thales Maciel 2026-04-26 21:32:57 -03:00
parent 74e5a7cedb
commit 74a2d064fd
No known key found for this signature in database
GPG key ID: 33112E6833C34679
3 changed files with 18 additions and 7 deletions

View file

@ -122,7 +122,7 @@ func (s *VMService) ensureWorkDisk(ctx context.Context, vm *model.VMRecord, imag
if _, err := s.runner.Run(ctx, "truncate", "-s", strconv.FormatInt(vm.Spec.WorkDiskSizeBytes, 10), vm.Runtime.WorkDiskPath); err != nil {
return workDiskPreparation{}, err
}
if _, err := s.runner.Run(ctx, "mkfs.ext4", "-F", "-E", "root_owner=0:0", vm.Runtime.WorkDiskPath); err != nil {
if _, err := s.runner.Run(ctx, "mkfs.ext4", "-F", "-E", system.MkfsExtraOptions, vm.Runtime.WorkDiskPath); err != nil {
return workDiskPreparation{}, err
}
return workDiskPreparation{}, nil

View file

@ -64,7 +64,7 @@ func BuildExt4(ctx context.Context, runner system.CommandRunner, srcDir, outFile
"-q",
"-d", srcDir,
"-L", "banger-rootfs",
"-E", "root_owner=0:0",
"-E", system.MkfsExtraOptions,
outFile,
)
if runErr != nil {

View file

@ -16,6 +16,17 @@ const (
minWorkSeedBytes int64 = 512 * 1024 * 1024
workSeedSlackBytes int64 = 256 * 1024 * 1024
workSeedRoundBytes int64 = 64 * 1024 * 1024
// MkfsExtraOptions are the -E flags banger always passes to
// mkfs.ext4 for VM-internal images. root_owner stamps inode 2
// (the fs root) as root:root so sshd's StrictModes accepts the
// resulting /root in the guest. lazy_itable_init + lazy_journal_init
// skip the inode-table and journal zeroing pass at mkfs time —
// the kernel does it lazily on first write inside the guest. On
// an 8 GiB work disk this saves roughly 500-700ms of host CPU/IO
// per 'banger vm create' for a one-time, small per-write cost
// inside the guest that nobody notices.
MkfsExtraOptions = "root_owner=0:0,lazy_itable_init=1,lazy_journal_init=1"
)
func CopyFilePreferClone(sourcePath, targetPath string) error {
@ -112,10 +123,10 @@ func BuildWorkSeedImage(ctx context.Context, runner CommandRunner, rootfsPath, o
if err := os.Truncate(outPath, sizeBytes); err != nil {
return err
}
// `-E root_owner=0:0` stamps inode 2 (which becomes /root in the
// guest) as root:root. Per-entry owners are forced via the ext4
// toolkit walk below.
if _, err := runner.Run(ctx, "mkfs.ext4", "-F", "-E", "root_owner=0:0", outPath); err != nil {
// root_owner stamps inode 2 (which becomes /root in the guest)
// as root:root. Per-entry owners are forced via the ext4 toolkit
// walk below.
if _, err := runner.Run(ctx, "mkfs.ext4", "-F", "-E", MkfsExtraOptions, outPath); err != nil {
return err
}
return ingestWorkSeedTree(ctx, runner, outPath, rootHome)
@ -144,7 +155,7 @@ func MaterializeWorkDisk(ctx context.Context, runner CommandRunner, seedPath, wo
if err := os.Truncate(workDiskPath, sizeBytes); err != nil {
return err
}
if _, err := runner.Run(ctx, "mkfs.ext4", "-F", "-E", "root_owner=0:0", workDiskPath); err != nil {
if _, err := runner.Run(ctx, "mkfs.ext4", "-F", "-E", MkfsExtraOptions, workDiskPath); err != nil {
return err
}