summaryrefslogtreecommitdiff
path: root/libpod/in_memory_state.go
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@pm.me>2021-03-02 11:58:32 -0500
committerMatthew Heon <matthew.heon@pm.me>2021-03-02 13:30:28 -0500
commit43e899c2ec2a874b9cb16f42bfd1e676981353b1 (patch)
treec8a42515aae42c0f50767323ed849ccbc8c2b2d5 /libpod/in_memory_state.go
parent426178a49991106ffe222f12cc42409ae78dd257 (diff)
downloadpodman-43e899c2ec2a874b9cb16f42bfd1e676981353b1.tar.gz
podman-43e899c2ec2a874b9cb16f42bfd1e676981353b1.tar.bz2
podman-43e899c2ec2a874b9cb16f42bfd1e676981353b1.zip
Rewrite Rename backend in a more atomic fashion
Move the core of renaming logic into the DB. This guarantees a lot more atomicity than we have right now (our current solution, removing the container from the DB and re-creating it, is *VERY* not atomic and prone to leaving a corrupted state behind if things go wrong. Moving things into the DB allows us to remove most, but not all, of this - there's still a potential scenario where the c/storage rename fails but the Podman rename succeeds, and we end up with a mismatched state. Signed-off-by: Matthew Heon <matthew.heon@pm.me>
Diffstat (limited to 'libpod/in_memory_state.go')
-rw-r--r--libpod/in_memory_state.go40
1 files changed, 40 insertions, 0 deletions
diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go
index 26f15d9c8..3875878ed 100644
--- a/libpod/in_memory_state.go
+++ b/libpod/in_memory_state.go
@@ -822,6 +822,46 @@ func (s *InMemoryState) RewriteContainerConfig(ctr *Container, newCfg *Container
return nil
}
+// SafeRewriteContainerConfig rewrites a container's configuration.
+// It's safer than RewriteContainerConfig, but still has limitations. Please
+// read the comment in state.go before using.
+func (s *InMemoryState) SafeRewriteContainerConfig(ctr *Container, oldName, newName string, newCfg *ContainerConfig) error {
+ if !ctr.valid {
+ return define.ErrCtrRemoved
+ }
+
+ if _, err := s.nameIndex.Get(newName); err == nil {
+ return errors.Wrapf(define.ErrCtrExists, "name %s is in use", newName)
+ }
+
+ // If the container does not exist, return error
+ stateCtr, ok := s.containers[ctr.ID()]
+ if !ok {
+ ctr.valid = false
+ return errors.Wrapf(define.ErrNoSuchCtr, "container with ID %s not found in state", ctr.ID())
+ }
+
+ // Change name in registry.
+ if s.namespace != "" {
+ nsIndex, ok := s.namespaceIndexes[s.namespace]
+ if !ok {
+ return define.ErrInternal
+ }
+ nsIndex.nameIndex.Release(oldName)
+ if err := nsIndex.nameIndex.Reserve(newName, ctr.ID()); err != nil {
+ return errors.Wrapf(err, "error registering name %s", newName)
+ }
+ }
+ s.nameIndex.Release(oldName)
+ if err := s.nameIndex.Reserve(newName, ctr.ID()); err != nil {
+ return errors.Wrapf(err, "error registering name %s", newName)
+ }
+
+ stateCtr.config = newCfg
+
+ return nil
+}
+
// RewritePodConfig rewrites a pod's configuration.
// This function is DANGEROUS, even with in-memory state.
// Please read the full comment on it in state.go before using it.