Skip to content

Commit 0b8f6f4

Browse files
committed
If booster fails to find root fs then print missing modules
Issue: #242
1 parent 9dc08c2 commit 0b8f6f4

File tree

7 files changed

+70
-10
lines changed

7 files changed

+70
-10
lines changed

docs/manpage.md

+4
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ Booster advantages:
5252

5353
* `modules_force_load` list of module names that are forcibly loaded during the boot process before switching into user-space. Any module in this list automatically added to the image so there is no need to duplicate it at `modules` property.
5454

55+
* `append_all_modaliases` is a boolean flag that instructs booster to add all hosts's module aliases to the booster image. This flag is useful for debugging boot timeout issues when some important modules are missed from the image. Setting the flag to `true` will help to print module names for aliases that were requested by kernel but missed in the image.
56+
5557
* `compression` is a flag that specifies compression for the output initramfs file. Currently supported algorithms are "zstd", "gzip", "xz", "lz4", "none". If no option specified then "zstd" is used as a default compression.
5658

5759
* `mount_timeout` timeout for waiting for the root filesystem to appear. The field format is a decimal number and then unit number. Valid units are "s", "m", "h". If no value specified then default timeout (3 minutes) is used. To disable the timeout completely specify "0s".
@@ -204,6 +206,8 @@ Regenerate the initramfs and reboot. Once inside busybox, get the logs and send
204206

205207
The logs will be in `/srv/atftp` on the server.
206208

209+
### Boot timeout
210+
If you got `booster: Timeout waiting for root filesystem` error please add `append_all_modaliases` config flag and rebuild the image. With this flag you'll get a list of modules that were requested by the kernel but absent in the booster image. Some of these modules might be required to boot your system.
207211

208212
## EXAMPLES
209213
Create an initramfs file specific for the current kernel/host. The output file is booster.img:

generator/config.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,12 @@ type UserConfig struct {
2727
Universal bool `yaml:",omitempty"`
2828
Modules string `yaml:",omitempty"` // comma separated list of extra modules to add to initramfs
2929
ModulesForceLoad string `yaml:"modules_force_load,omitempty"` // comma separated list of extra modules to load at the boot time
30-
Compression string `yaml:",omitempty"` // output file compression
31-
MountTimeout string `yaml:"mount_timeout,omitempty"` // timeout for waiting for the rootfs mounted
32-
ExtraFiles string `yaml:"extra_files,omitempty"` // comma-separated list of files to add to image
33-
StripBinaries bool `yaml:"strip,omitempty"` // if strip symbols from the binaries, shared libraries and kernel modules
34-
EnableVirtualConsole bool `yaml:"vconsole,omitempty"` // configure virtual console at boot time using config from https://www.freedesktop.org/software/systemd/man/vconsole.conf.html
30+
AppendAllModAliases bool `yaml:"append_all_modaliases,omitempty"`
31+
Compression string `yaml:",omitempty"` // output file compression
32+
MountTimeout string `yaml:"mount_timeout,omitempty"` // timeout for waiting for the rootfs mounted
33+
ExtraFiles string `yaml:"extra_files,omitempty"` // comma-separated list of files to add to image
34+
StripBinaries bool `yaml:"strip,omitempty"` // if strip symbols from the binaries, shared libraries and kernel modules
35+
EnableVirtualConsole bool `yaml:"vconsole,omitempty"` // configure virtual console at boot time using config from https://www.freedesktop.org/software/systemd/man/vconsole.conf.html
3536
EnableLVM bool `yaml:"enable_lvm"`
3637
EnableMdraid bool `yaml:"enable_mdraid"`
3738
MdraidConfigPath string `yaml:"mdraid_config_path"`
@@ -142,6 +143,7 @@ func readGeneratorConfig(file string) (*generatorConfig, error) {
142143
conf.readDeviceAliases = readDeviceAliases
143144
conf.readHostModules = readHostModules
144145
conf.readModprobeOptions = readModprobeOptions
146+
conf.appendAllModAliases = u.AppendAllModAliases
145147
conf.stripBinaries = u.StripBinaries || opts.BuildCommand.Strip
146148
conf.enableLVM = u.EnableLVM
147149
conf.enableMdraid = u.EnableMdraid

generator/generator.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type generatorConfig struct {
2121
universal bool
2222
modules []string // extra modules to add
2323
modulesForceLoad []string // extra modules to load at the boot time
24+
appendAllModAliases bool
2425
compression string
2526
timeout time.Duration
2627
extraFiles []string
@@ -214,10 +215,15 @@ func generateInitRamfs(conf *generatorConfig) error {
214215
return err
215216
}
216217

217-
// collect aliases for required modules only
218-
aliases, err := kmod.filterAliasesForRequiredModules(conf)
219-
if err != nil {
220-
return err
218+
var aliases []alias
219+
if conf.appendAllModAliases {
220+
aliases = kmod.aliases
221+
} else {
222+
// collect aliases for required modules only
223+
aliases, err = kmod.filterAliasesForRequiredModules(conf)
224+
if err != nil {
225+
return err
226+
}
221227
}
222228
if err := img.appendAliasesFile(aliases); err != nil {
223229
return err

init/main.go

+23-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ var (
4747
rootRo, rootRw bool
4848

4949
zfsDataset string
50+
51+
errRootMountTimeout = fmt.Errorf("Timeout waiting for root filesystem")
5052
)
5153

5254
type set map[string]bool
@@ -858,7 +860,7 @@ func boost() error {
858860
// TODO: cancellable, timeout context?
859861
timeout := waitTimeout(&rootMounted, time.Duration(config.MountTimeout)*time.Second)
860862
if timeout {
861-
return fmt.Errorf("Timeout waiting for root filesystem")
863+
return errRootMountTimeout
862864
}
863865
} else {
864866
// wait for mount forever
@@ -991,6 +993,22 @@ func reboot() {
991993
_ = unix.Reboot(unix.LINUX_REBOOT_CMD_RESTART)
992994
}
993995

996+
func printMissingModules() {
997+
missingModulesMutex.Lock()
998+
defer missingModulesMutex.Unlock()
999+
1000+
if len(missingModules) == 0 {
1001+
return
1002+
}
1003+
1004+
mods := make([]string, 0, len(missingModules))
1005+
for k := range missingModules {
1006+
mods = append(mods, k)
1007+
}
1008+
1009+
warning("Following modules were requested by kernel but not present in the image: [%s]. Please check the list and see if any of the modules required to detect your root filesystem.", strings.Join(mods, " "))
1010+
}
1011+
9941012
func main() {
9951013
readStartTime()
9961014

@@ -1002,6 +1020,10 @@ func main() {
10021020
if err := boost(); err != nil {
10031021
// if it does then it indicates some problem
10041022
severe("%v", err)
1023+
if errors.Is(err, errRootMountTimeout) {
1024+
// if we fail to detect the root filesystem maybe we are missing some kernel modules needed for storage devices?
1025+
printMissingModules()
1026+
}
10051027
}
10061028
emergencyShell()
10071029

init/module.go

+9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"bufio"
5+
"errors"
56
"os"
67
"path/filepath"
78
"strings"
@@ -17,6 +18,9 @@ var (
1718
loadingModules = make(map[string][]*sync.WaitGroup)
1819
loadingModulesWg sync.WaitGroup // total number of modules being loaded
1920
modulesMutex sync.Mutex
21+
22+
missingModules = make(map[string]bool) // set of modules that kernel wanted to load via aliases but they were missing in the image
23+
missingModulesMutex sync.Mutex
2024
)
2125

2226
type alias struct{ pattern, module string } // module alias info
@@ -66,6 +70,11 @@ func loadModuleUnlocked(wg *sync.WaitGroup, modules ...string) {
6670
depsWg.Wait()
6771
if err := finitModule(mod); err != nil {
6872
info("finit(%v): %v", mod, err)
73+
if errors.Is(err, os.ErrNotExist) {
74+
missingModulesMutex.Lock()
75+
missingModules[mod] = true
76+
missingModulesMutex.Unlock()
77+
}
6978
}
7079

7180
modulesMutex.Lock()

tests/integration_test.go

+14
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,20 @@ func TestMountTimeout(t *testing.T) {
159159
require.NoError(t, vm.ConsoleExpect("Timeout waiting for root filesystem"))
160160
}
161161

162+
func TestMountTimeoutWithAllModaliases(t *testing.T) {
163+
vm, err := buildVmInstance(t, Opts{
164+
kernelArgs: []string{"root=/dev/sda"},
165+
modules: "-*",
166+
mountTimeout: 1,
167+
appendAllModAliases: true,
168+
})
169+
require.NoError(t, err)
170+
defer vm.Kill()
171+
172+
require.NoError(t, vm.ConsoleExpect("Timeout waiting for root filesystem"))
173+
require.NoError(t, vm.ConsoleExpect("Following modules were requested by kernel but not present in the image: ["))
174+
}
175+
162176
func TestFsck(t *testing.T) {
163177
vm, err := buildVmInstance(t, Opts{
164178
compression: "none",

tests/util.go

+3
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ type GeneratorConfig struct {
236236
ModulesForceLoad string `yaml:"modules_force_load,omitempty"` // comma separated list of extra modules to load at the boot time
237237
Compression string `yaml:",omitempty"`
238238
MountTimeout string `yaml:"mount_timeout,omitempty"`
239+
AppendAllModAliases bool `yaml:"append_all_modaliases,omitempty"`
239240
ExtraFiles string `yaml:"extra_files,omitempty"`
240241
StripBinaries bool `yaml:"strip,omitempty"` // strip symbols from the binaries, shared libraries and kernel modules
241242
EnableVirtualConsole bool `yaml:"vconsole,omitempty"`
@@ -265,6 +266,7 @@ func generateBoosterConfig(output string, opts Opts) error {
265266
conf.Universal = true
266267
conf.Compression = opts.compression
267268
conf.MountTimeout = strconv.Itoa(opts.mountTimeout) + "s"
269+
conf.AppendAllModAliases = opts.appendAllModAliases
268270
conf.ExtraFiles = opts.extraFiles
269271
conf.StripBinaries = opts.stripBinaries
270272
conf.EnableVirtualConsole = opts.enableVirtualConsole
@@ -305,6 +307,7 @@ type Opts struct {
305307
asIso bool // generate ISO file instead of *.raw
306308
scriptEnvvars []string
307309
mountTimeout int // in seconds
310+
appendAllModAliases bool
308311
extraFiles string
309312
stripBinaries bool
310313
enableVirtualConsole bool

0 commit comments

Comments
 (0)