mirror of
https://github.com/containers/podman.git
synced 2025-06-27 13:38:49 +08:00
Use atomic config writing strategy for podman machine config files
Windows: Flush machine config writes before renaming Windows: Previously this code was changed to improve atomicity by changing the persitence approach to a two-step process (write + rename). However, the first-step write operation was not fully flushed, leading to the possibility of incomplete writes. [NO NEW TESTS NEEDED] Signed-off-by: Jason T. Greene <jason.greene@redhat.com>
This commit is contained in:
@ -29,6 +29,7 @@ import (
|
|||||||
"github.com/containers/podman/v4/pkg/rootless"
|
"github.com/containers/podman/v4/pkg/rootless"
|
||||||
"github.com/containers/podman/v4/utils"
|
"github.com/containers/podman/v4/utils"
|
||||||
"github.com/containers/storage/pkg/homedir"
|
"github.com/containers/storage/pkg/homedir"
|
||||||
|
"github.com/containers/storage/pkg/ioutils"
|
||||||
"github.com/digitalocean/go-qemu/qmp"
|
"github.com/digitalocean/go-qemu/qmp"
|
||||||
"github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -1560,14 +1561,22 @@ func (v *MachineVM) writeConfig() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Write the JSON file
|
// Write the JSON file
|
||||||
b, err := json.MarshalIndent(v, "", " ")
|
opts := &ioutils.AtomicFileWriterOptions{ExplicitCommit: true}
|
||||||
|
w, err := ioutils.NewAtomicFileWriterWithOpts(v.ConfigPath.GetPath(), 0644, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := os.WriteFile(v.ConfigPath.GetPath(), b, 0644); err != nil {
|
defer w.Close()
|
||||||
|
|
||||||
|
enc := json.NewEncoder(w)
|
||||||
|
enc.SetIndent("", " ")
|
||||||
|
|
||||||
|
if err := enc.Encode(v); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
// Commit the changes to disk if no errors
|
||||||
|
return w.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// getImageFile wrapper returns the path to the image used
|
// getImageFile wrapper returns the path to the image used
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/containers/podman/v4/pkg/machine"
|
"github.com/containers/podman/v4/pkg/machine"
|
||||||
"github.com/containers/podman/v4/utils"
|
"github.com/containers/podman/v4/utils"
|
||||||
"github.com/containers/storage/pkg/homedir"
|
"github.com/containers/storage/pkg/homedir"
|
||||||
|
"github.com/containers/storage/pkg/ioutils"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/text/encoding/unicode"
|
"golang.org/x/text/encoding/unicode"
|
||||||
"golang.org/x/text/transform"
|
"golang.org/x/text/transform"
|
||||||
@ -450,21 +451,22 @@ func downloadDistro(v *MachineVM, opts machine.InitOptions) error {
|
|||||||
func (v *MachineVM) writeConfig() error {
|
func (v *MachineVM) writeConfig() error {
|
||||||
const format = "could not write machine json config: %w"
|
const format = "could not write machine json config: %w"
|
||||||
jsonFile := v.ConfigPath
|
jsonFile := v.ConfigPath
|
||||||
tmpFile, err := getConfigPathExt(v.Name, "tmp")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := json.MarshalIndent(v, "", " ")
|
opts := &ioutils.AtomicFileWriterOptions{ExplicitCommit: true}
|
||||||
|
w, err := ioutils.NewAtomicFileWriterWithOpts(jsonFile, 0644, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(format, err)
|
return fmt.Errorf(format, err)
|
||||||
}
|
}
|
||||||
|
defer w.Close()
|
||||||
|
|
||||||
if err := os.WriteFile(tmpFile, b, 0644); err != nil {
|
enc := json.NewEncoder(w)
|
||||||
|
enc.SetIndent("", " ")
|
||||||
|
if err := enc.Encode(v); err != nil {
|
||||||
return fmt.Errorf(format, err)
|
return fmt.Errorf(format, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.Rename(tmpFile, jsonFile); err != nil {
|
// Commit the changes to disk if no error has occurred
|
||||||
|
if err := w.Commit(); err != nil {
|
||||||
return fmt.Errorf(format, err)
|
return fmt.Errorf(format, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user