From aee2bbde84d32045ac3d516bc00322b9d9d418aa Mon Sep 17 00:00:00 2001 From: Itxaka Date: Thu, 9 Feb 2023 12:35:45 +0100 Subject: [PATCH] Deal nicely with already mounted errors Signed-off-by: Itxaka --- internal/constants/constants.go | 4 ++++ pkg/mount/fs.go | 10 ++------- pkg/mount/mount.go | 37 ++++++++++++++++++++++++--------- pkg/mount/operation.go | 9 ++++---- 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 72d24ba..347fe8a 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -1,8 +1,12 @@ package constants +import "errors" + const PersistentStateTarget = "/usr/local/.state" func DefaultRWPaths() []string { // Default RW_PATHS to mount if there are none defined return []string{"/etc", "/root", "/home", "/opt", "/srv", "/usr/local", "/var"} } + +var ErrAlreadyMounted = errors.New("already mounted") diff --git a/pkg/mount/fs.go b/pkg/mount/fs.go index 781e776..80a91eb 100644 --- a/pkg/mount/fs.go +++ b/pkg/mount/fs.go @@ -27,21 +27,15 @@ func baseOverlay(overlay Overlay) (mountOperation, error) { switch t { case "tmpfs": tmpMount := mount.Mount{Type: "tmpfs", Source: "tmpfs", Options: []string{fmt.Sprintf("size=%s", dat[1])}} - err := mount.All([]mount.Mount{tmpMount}, overlay.Base) tmpFstab := internalUtils.MountToFstab(tmpMount) - // TODO: Fix this - // Currently stores it wrongly the the fstab as `tmpfs tmpfs:20% tmpfs size=20% 0 0` - // Correct format should be `tmpfs /run/overlay tmpfs defaults,size=20% 0 0` tmpFstab.File = internalUtils.CleanSysrootForFstab(overlay.Base) return mountOperation{ MountOption: tmpMount, FstabEntry: *tmpFstab, Target: overlay.Base, - }, err + }, nil case "block": blockMount := mount.Mount{Type: "auto", Source: dat[1]} - err := mount.All([]mount.Mount{blockMount}, overlay.Base) - tmpFstab := internalUtils.MountToFstab(blockMount) // TODO: Check if this is properly written to fstab, currently have no examples tmpFstab.File = internalUtils.CleanSysrootForFstab(overlay.Base) @@ -51,7 +45,7 @@ func baseOverlay(overlay Overlay) (mountOperation, error) { MountOption: blockMount, FstabEntry: *tmpFstab, Target: overlay.Base, - }, err + }, nil default: return mountOperation{}, fmt.Errorf("invalid overlay backing base type") } diff --git a/pkg/mount/mount.go b/pkg/mount/mount.go index 83a99df..18b62bd 100644 --- a/pkg/mount/mount.go +++ b/pkg/mount/mount.go @@ -2,6 +2,7 @@ package mount import ( "context" + "errors" "fmt" "github.com/kairos-io/immucore/internal/constants" "os" @@ -132,11 +133,16 @@ func (s *State) MountOP(what, where, t string, options []string, timeout time.Du } err = op.run() - if err != nil { + + if err == nil { + s.fstabs = append(s.fstabs, tmpFstab) + } + + // only continue the loop if it's an error and not an already mounted error + if err != nil && !errors.Is(err, constants.ErrAlreadyMounted) { continue } - s.fstabs = append(s.fstabs, tmpFstab) return nil case <-c.Done(): e := fmt.Errorf("context canceled") @@ -328,7 +334,12 @@ func (s *State) Register(g *herd.Graph) error { return err } s.fstabs = append(s.fstabs, &op.FstabEntry) - return op.run() + err = op.run() + // Don't return error if it's an already mounted error + if err != nil && errors.Is(err, constants.ErrAlreadyMounted) { + return nil + } + return err }, ), ) @@ -347,17 +358,21 @@ func (s *State) Register(g *herd.Graph) error { mountRootCondition, herd.WithCallback( func(ctx context.Context) error { - var err error + var err *multierror.Error for _, p := range s.OverlayDirs { op, err := mountWithBaseOverlay(p, s.Rootdir, "/run/overlay") if err != nil { return err } s.fstabs = append(s.fstabs, &op.FstabEntry) - err = multierror.Append(err, op.run()) + err2 := op.run() + // Append to errors only if it's not an already mounted error + if err2 != nil && !errors.Is(err2, constants.ErrAlreadyMounted) { + err = multierror.Append(err, err2) + } } - return err + return err.ErrorOrNil() }, ), ) @@ -416,13 +431,15 @@ func (s *State) Register(g *herd.Graph) error { } op := mountBind(p, s.Rootdir, s.StateDir) err2 := op.run() - if err2 != nil { - log.Logger.Err(err2).Send() - err = multierror.Append(err, err2) - } else { + if err2 == nil { // Only append to fstabs if there was no error, otherwise we will try to mount it after switch_root s.fstabs = append(s.fstabs, &op.FstabEntry) } + // Append to errors only if it's not an already mounted error + if err2 != nil && !errors.Is(err2, constants.ErrAlreadyMounted) { + log.Logger.Err(err2).Send() + err = multierror.Append(err, err2) + } } log.Logger.Err(err.ErrorOrNil()).Send() return err.ErrorOrNil() diff --git a/pkg/mount/operation.go b/pkg/mount/operation.go index 4e7ee5b..53b135a 100644 --- a/pkg/mount/operation.go +++ b/pkg/mount/operation.go @@ -3,6 +3,7 @@ package mount import ( "github.com/containerd/containerd/mount" "github.com/deniswernert/go-fstab" + "github.com/kairos-io/immucore/internal/constants" "github.com/moby/sys/mountinfo" "github.com/rs/zerolog" "github.com/rs/zerolog/log" @@ -20,19 +21,19 @@ func (m mountOperation) run() error { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger() if m.PrepareCallback != nil { if err := m.PrepareCallback(); err != nil { - log.Logger.Err(err).Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Msg("executing mount callback") + log.Logger.Err(err).Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Strs("options", m.MountOption.Options).Msg("executing mount callback") return err } } //TODO: not only check if mounted but also if the type,options and source are the same? mounted, err := mountinfo.Mounted(m.Target) if err != nil { - log.Logger.Err(err).Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Msg("checking mount status") + log.Logger.Err(err).Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Strs("options", m.MountOption.Options).Msg("checking mount status") return err } if mounted { - log.Logger.Debug().Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Msg("Already mounted") - return nil + log.Logger.Debug().Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Strs("options", m.MountOption.Options).Msg("Already mounted") + return constants.ErrAlreadyMounted } return mount.All([]mount.Mount{m.MountOption}, m.Target) }