Skip to content

Commit

Permalink
fix: skip writing the file if the contents haven't changed
Browse files Browse the repository at this point in the history
As the controller reconciles every /etc file present, it might be called
multiple times for the same file, even if the actual contents haven't
changed.

Rewriting the file might lead to some concurrent process seeing
incomplete file contents more often than needed.

Signed-off-by: Andrey Smirnov <[email protected]>
  • Loading branch information
smira committed Dec 4, 2023
1 parent 6329222 commit dbf274d
Showing 1 changed file with 13 additions and 1 deletion.
14 changes: 13 additions & 1 deletion internal/app/machined/pkg/controllers/files/etcfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package files

import (
"bytes"
"context"
"errors"
"fmt"
Expand Down Expand Up @@ -132,7 +133,7 @@ func (ctrl *EtcFileController) Run(ctx context.Context, r controller.Runtime, lo

logger.Debug("writing file contents", zap.String("dst", dst), zap.Stringer("version", spec.Metadata().Version()))

if err = os.WriteFile(dst, spec.TypedSpec().Contents, spec.TypedSpec().Mode); err != nil {
if err = updateFile(dst, spec.TypedSpec().Contents, spec.TypedSpec().Mode); err != nil {
return fmt.Errorf("error updating %q: %w", dst, err)
}

Expand Down Expand Up @@ -190,3 +191,14 @@ func createBindMount(src, dst string, mode os.FileMode) (err error) {

return nil
}

// updateFile is like `os.WriteFile`, but it will only update the file if the
// contents have changed.
func updateFile(filename string, contents []byte, mode os.FileMode) error {
oldContents, err := os.ReadFile(filename)
if err == nil && bytes.Equal(oldContents, contents) {
return nil
}

return os.WriteFile(filename, contents, mode)
}

0 comments on commit dbf274d

Please sign in to comment.