diff --git a/internal/utils/mounts.go b/internal/utils/mounts.go index 7538d1c..63913d2 100644 --- a/internal/utils/mounts.go +++ b/internal/utils/mounts.go @@ -119,3 +119,53 @@ func CleanSysrootForFstab(path string) string { } return cleaned } + +// Fsck will run fsck over the device +// options are set on cmdline, but they are for systemd-fsck, +// so we need to interpret ourselves +func Fsck(device string) error { + if device == "tmpfs" { + return nil + } + mode := ReadCMDLineArg("fsck.mode=") + repair := ReadCMDLineArg("fsck.repair=") + // Be safe with defaults + if len(mode) == 0 { + mode = []string{"auto"} + } + if len(repair) == 0 { + repair = []string{"preen"} + } + args := []string{"fsck", device} + // Check the mode + // skip means just skip the fsck + // force means force even if fs is deemed clean + // auto or others means normal fsck call + switch mode[0] { + case "skip": + return nil + case "force": + args = append(args, "-f") + } + + // Check repair type + // preen means try to fix automatically + // yes means say yes to everything (potentially destructive) + // no means say no to everything + switch repair[0] { + case "preen": + args = append(args, "-a") + case "yes": + args = append(args, "-y") + case "no": + args = append(args, "-n") + } + cmd := strings.Join(args, " ") + log.Logger.Debug().Str("cmd", cmd).Msg("fsck command") + out, e := utils.SH(cmd) + log.Logger.Debug().Str("output", out).Msg("fsck output") + if e != nil { + log.Logger.Warn().Str("error", e.Error()).Str("what", device).Msg("fsck") + } + return e +} diff --git a/pkg/mount/dag_steps.go b/pkg/mount/dag_steps.go index 9e8e72a..dc06c86 100644 --- a/pkg/mount/dag_steps.go +++ b/pkg/mount/dag_steps.go @@ -56,7 +56,7 @@ func (s *State) MountRootDagStep(g *herd.Graph) error { log.Logger.Debug().Str("targetImage", s.TargetImage).Str("path", s.Rootdir).Str("TargetDevice", s.TargetDevice).Msg("Not mounting loop, already mounted") return nil } - // TODO: squashfs recovery image? + _ = internalUtils.Fsck(s.path("/run/initramfs/cos-state", s.TargetImage)) cmd := fmt.Sprintf("losetup --show -f %s", s.path("/run/initramfs/cos-state", s.TargetImage)) _, err := utils.SH(cmd) s.LogIfError(err, "losetup") diff --git a/pkg/mount/state.go b/pkg/mount/state.go index fd7115b..523d512 100644 --- a/pkg/mount/state.go +++ b/pkg/mount/state.go @@ -116,6 +116,10 @@ func (s *State) MountOP(what, where, t string, options []string, timeout time.Du MountOption: mountPoint, FstabEntry: *tmpFstab, Target: where, + PrepareCallback: func() error { + _ = internalUtils.Fsck(what) + return nil + }, } err = op.run()