mirror of
https://github.com/containers/podman.git
synced 2025-08-06 11:32:07 +08:00
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>
This commit is contained in:
@ -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.
|
||||
|
Reference in New Issue
Block a user