With THP 'always' journald's mmapped journal files sit in 2 MiB folios, so each small journal write dirties and writes back 2 MiB; on the control node that saturated the root mirror holding the bus store and the store, and the controller lost its lease. The module sets the mode from a per-machine setting (default always, the kernel's own, so assigning it changes nothing until a machine sets madvise), verifies it took, rotates the journal once so new files are mapped under the new mode, gives back what it found when stopped, and serves kernel_huge_pages to measure file_thp per unit.
182 lines
6.4 KiB
Go
182 lines
6.4 KiB
Go
package main
|
|
|
|
// The module's shape (novox/hq issue 746): the setting's default is what the kernel boots with, so
|
|
// assigning the module changes nothing until a machine sets another value; the script is written into the
|
|
// module's own state and run by a oneshot unit that is restarted whenever the script (and so the setting)
|
|
// or the unit changes; and the script itself sets, verifies, gives back and refuses as it says.
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestTheDefaultChangesNothingAndTheUnitFollowsTheSetting(t *testing.T) {
|
|
m := manifest(t)
|
|
s := m.Settings["transparent-huge-pages"]
|
|
if s["kind"] != "preference" || s["default"] != "always" || s["why"] == "" {
|
|
t.Fatalf("the setting: %v", s)
|
|
}
|
|
var ids []string
|
|
for _, r := range m.Resources {
|
|
ids = append(ids, r["id"].(string))
|
|
}
|
|
if strings.Join(ids, " ") != "state huge-pages unit apply" {
|
|
t.Fatalf("order: %v", ids)
|
|
}
|
|
script := m.resource(t, "huge-pages")
|
|
// The script runs as root, so the setting it is written from is set at the terminal alone (issue 339).
|
|
if script["path"] != "${dir:state}/huge-pages" || script["mode"] != "0755" || script["trusted"] != true ||
|
|
!strings.Contains(script["content"].(string), "want='${setting:transparent-huge-pages}'") {
|
|
t.Fatalf("the script: %v", script["path"])
|
|
}
|
|
unit := m.resource(t, "unit")["content"].(string)
|
|
for _, line := range []string{"Type=oneshot", "RemainAfterExit=yes", "ExecStart=${dir:state}/huge-pages apply",
|
|
"ExecStop=${dir:state}/huge-pages restore", "WantedBy=sysinit.target", "DefaultDependencies=no"} {
|
|
if !strings.Contains(unit, line+"\n") {
|
|
t.Errorf("the unit lacks %q", line)
|
|
}
|
|
}
|
|
apply := m.resource(t, "apply")
|
|
if apply["unit"] != "mesh-kernel-huge-pages.service" || apply["state"] != "running" || apply["boot"] != "enabled" {
|
|
t.Fatalf("apply: %v", apply)
|
|
}
|
|
if on := apply["restart-on"].([]any); len(on) != 2 || on[0] != "huge-pages" || on[1] != "unit" {
|
|
t.Fatalf("restart-on: %v", on)
|
|
}
|
|
if h := apply["health"].(map[string]any); h["kind"] != "unit" {
|
|
t.Fatalf("health: %v", h)
|
|
}
|
|
}
|
|
|
|
// bed is the script as the mesh writes it for one value of the setting, a stand-in transparent_hugepage
|
|
// directory, the module's state, and a PATH whose journalctl records that it was asked to rotate.
|
|
type bed struct {
|
|
script, sys, state, rotated, path string
|
|
}
|
|
|
|
func newBed(t *testing.T, want, found string) bed {
|
|
t.Helper()
|
|
dir := t.TempDir()
|
|
b := bed{script: filepath.Join(dir, "huge-pages"), sys: filepath.Join(dir, "thp"), state: filepath.Join(dir, "state"),
|
|
rotated: filepath.Join(dir, "rotated")}
|
|
content := manifest(t).resource(t, "huge-pages")["content"].(string)
|
|
content = strings.ReplaceAll(content, "${setting:transparent-huge-pages}", want)
|
|
content = strings.ReplaceAll(content, "${dir:state}", b.state)
|
|
if strings.Contains(content, "${") {
|
|
t.Fatalf("a substitution the test does not make is left in the script")
|
|
}
|
|
bin := filepath.Join(dir, "bin")
|
|
for _, d := range []string{b.sys, b.state, bin} {
|
|
if err := os.MkdirAll(d, 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
write(t, b.script, content, 0o755)
|
|
write(t, filepath.Join(b.sys, "enabled"), found, 0o644)
|
|
write(t, filepath.Join(bin, "journalctl"), "#!/bin/sh\necho \"$@\" >>"+b.rotated+"\n", 0o755)
|
|
b.path = bin + string(os.PathListSeparator) + os.Getenv("PATH")
|
|
return b
|
|
}
|
|
|
|
func write(t *testing.T, p, content string, mode os.FileMode) {
|
|
t.Helper()
|
|
if err := os.WriteFile(p, []byte(content), mode); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func (b bed) run(t *testing.T, verb string) (string, error) {
|
|
t.Helper()
|
|
cmd := exec.Command("sh", b.script, verb, b.sys, b.state)
|
|
cmd.Env = append(os.Environ(), "PATH="+b.path)
|
|
out, err := cmd.CombinedOutput()
|
|
return string(out), err
|
|
}
|
|
|
|
func (b bed) file(t *testing.T, p string) string {
|
|
t.Helper()
|
|
raw, err := os.ReadFile(p)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return string(raw)
|
|
}
|
|
|
|
func TestApplySetsTheModeRotatesTheJournalOnceAndRestoreGivesBackWhatWasFound(t *testing.T) {
|
|
// novox's file on 2026-10-14, read through node-reads.
|
|
b := newBed(t, "madvise", "[always] madvise never\n")
|
|
out, err := b.run(t, "apply")
|
|
if err != nil || !strings.Contains(out, "always -> madvise") {
|
|
t.Fatalf("apply: %v %s", err, out)
|
|
}
|
|
if got := b.file(t, filepath.Join(b.sys, "enabled")); got != "madvise\n" {
|
|
t.Fatalf("written: %q", got)
|
|
}
|
|
if got := b.file(t, filepath.Join(b.state, "found")); got != "always\n" {
|
|
t.Fatalf("found: %q", got)
|
|
}
|
|
if got := b.file(t, b.rotated); got != "--rotate\n" {
|
|
t.Fatalf("rotation: %q", got)
|
|
}
|
|
// Applied again (a restart with the same value): nothing written, nothing rotated, found kept.
|
|
if out, err := b.run(t, "apply"); err != nil || !strings.Contains(out, "madvise, as set") {
|
|
t.Fatalf("again: %v %s", err, out)
|
|
}
|
|
if got := b.file(t, b.rotated); got != "--rotate\n" {
|
|
t.Fatalf("rotated again: %q", got)
|
|
}
|
|
if out, err := b.run(t, "restore"); err != nil || !strings.Contains(out, "back to always") {
|
|
t.Fatalf("restore: %v %s", err, out)
|
|
}
|
|
if got := b.file(t, filepath.Join(b.sys, "enabled")); got != "always\n" {
|
|
t.Fatalf("restored: %q", got)
|
|
}
|
|
}
|
|
|
|
func TestAlwaysIsSetWithoutRotating(t *testing.T) {
|
|
b := newBed(t, "always", "always [madvise] never\n")
|
|
if out, err := b.run(t, "apply"); err != nil || !strings.Contains(out, "madvise -> always") {
|
|
t.Fatalf("apply: %v %s", err, out)
|
|
}
|
|
if got := b.file(t, b.rotated); got != "" {
|
|
t.Fatalf("rotated for always: %q", got)
|
|
}
|
|
}
|
|
|
|
func TestAValueTheKernelDoesNotTakeIsRefusedBeforeAnythingIsWritten(t *testing.T) {
|
|
b := newBed(t, "sometimes", "[always] madvise never\n")
|
|
out, err := b.run(t, "apply")
|
|
if err == nil || !strings.Contains(out, "takes always, madvise or never") {
|
|
t.Fatalf("accepted: %v %s", err, out)
|
|
}
|
|
if got := b.file(t, filepath.Join(b.sys, "enabled")); got != "[always] madvise never\n" {
|
|
t.Fatalf("written anyway: %q", got)
|
|
}
|
|
}
|
|
|
|
func TestAWriteThatDoesNotTakeFailsTheUnit(t *testing.T) {
|
|
if os.Getuid() == 0 {
|
|
t.Skip("root writes a read-only file")
|
|
}
|
|
b := newBed(t, "madvise", "[always] madvise never\n")
|
|
if err := os.Chmod(filepath.Join(b.sys, "enabled"), 0o444); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if out, err := b.run(t, "apply"); err == nil {
|
|
t.Fatalf("a refused write passed: %s", out)
|
|
}
|
|
}
|
|
|
|
func TestAKernelWithoutHugePagesIsSaid(t *testing.T) {
|
|
b := newBed(t, "madvise", "")
|
|
if err := os.Remove(filepath.Join(b.sys, "enabled")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if out, err := b.run(t, "apply"); err == nil || !strings.Contains(out, "built without transparent huge pages") {
|
|
t.Fatalf("%v %s", err, out)
|
|
}
|
|
}
|