mirror of
https://github.com/containers/podman
synced 2024-10-20 17:23:30 +00:00
Move RenumberLocks into runtime init
We can't do renumbering after init - we need to open a potentially invalid locks file (too many/too few locks), and then potentially delete the old locks and make new ones. We need to be in init to bypass the checks that would otherwise make this impossible. This leaves us with two choices: make RenumberLocks a separate entrypoint from NewRuntime, duplicating a lot of configuration load code (we need to know where the locks live, how many there are, etc) - or modify NewRuntime to allow renumbering during it. Previous experience says the first is not really a viable option and produces massive code bloat, so the second it is. Signed-off-by: Matthew Heon <matthew.heon@pm.me>
This commit is contained in:
parent
ca8ae877c1
commit
a72025d6fd
|
@ -394,6 +394,26 @@ func WithDefaultInfraCommand(cmd string) RuntimeOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WithRenumber instructs libpod to perform a lock renumbering instead of a
|
||||
// normal init.
|
||||
// When this is specified, no valid runtime will be returned by NewRuntime.
|
||||
// Instead, libpod will reinitialize lock numbers on all pods and containers,
|
||||
// shut down the runtime, and return.
|
||||
// Renumber is intended to be used from a dedicated entrypoint, where it will
|
||||
// handle a changed maximum number of locks and return, with the program
|
||||
// exiting after that.
|
||||
func WithRenumber() RuntimeOption {
|
||||
return func(rt *Runtime) error {
|
||||
if rt.valid {
|
||||
return ErrRuntimeFinalized
|
||||
}
|
||||
|
||||
rt.doRenumber = true
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Container Creation Options
|
||||
|
||||
// WithShmDir sets the directory that should be mounted on /dev/shm.
|
||||
|
|
|
@ -79,7 +79,8 @@ type RuntimeOption func(*Runtime) error
|
|||
|
||||
// Runtime is the core libpod runtime
|
||||
type Runtime struct {
|
||||
config *RuntimeConfig
|
||||
config *RuntimeConfig
|
||||
|
||||
state State
|
||||
store storage.Store
|
||||
storageService *storageService
|
||||
|
@ -88,12 +89,15 @@ type Runtime struct {
|
|||
netPlugin ocicni.CNIPlugin
|
||||
ociRuntimePath OCIRuntimePath
|
||||
conmonPath string
|
||||
valid bool
|
||||
lock sync.RWMutex
|
||||
imageRuntime *image.Runtime
|
||||
firewallBackend firewall.FirewallBackend
|
||||
lockManager lock.Manager
|
||||
configuredFrom *runtimeConfiguredFrom
|
||||
|
||||
doRenumber bool
|
||||
|
||||
valid bool
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
// OCIRuntimePath contains information about an OCI runtime.
|
||||
|
@ -753,6 +757,13 @@ func makeRuntime(runtime *Runtime) (err error) {
|
|||
aliveLock.Unlock()
|
||||
}
|
||||
}()
|
||||
// If we're renumbering locks, do it now.
|
||||
// It breaks out of normal runtime init, and will not return a valid
|
||||
// runtime.
|
||||
if runtime.doRenumber {
|
||||
return runtime.renumberLocks()
|
||||
}
|
||||
|
||||
_, err = os.Stat(runtimeAliveFile)
|
||||
if err != nil {
|
||||
// If the file doesn't exist, we need to refresh the state
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
package libpod
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/storage"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// RenumberLocks reassigns lock numbers for all containers, pods, and volumes in
|
||||
// the state.
|
||||
// renumberLocks reassigns lock numbers for all containers and pods in the
|
||||
// state.
|
||||
// It renders the runtime it is called on, and all container/pod/volume structs
|
||||
// from that runtime, unusable, and requires that a new runtime be initialized
|
||||
// after it is called.
|
||||
|
@ -18,24 +15,7 @@ import (
|
|||
// lock as read, renumber attempting to take a write lock?
|
||||
// The alternative is some sort of session tracking, and I don't know how
|
||||
// reliable that can be.
|
||||
func (r *Runtime) RenumberLocks() error {
|
||||
r.lock.Lock()
|
||||
locked := true
|
||||
defer func() {
|
||||
if locked {
|
||||
r.lock.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
runtimeAliveLock := filepath.Join(r.config.TmpDir, "alive.lck")
|
||||
aliveLock, err := storage.GetLockfile(runtimeAliveLock)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error acquiring runtime init lock")
|
||||
}
|
||||
aliveLock.Lock()
|
||||
// It's OK to defer until Shutdown() has run, so no need to check locked
|
||||
defer aliveLock.Unlock()
|
||||
|
||||
func (r *Runtime) renumberLocks() error {
|
||||
// Start off by deallocating all locks
|
||||
if err := r.lockManager.FreeAllLocks(); err != nil {
|
||||
return err
|
||||
|
@ -76,8 +56,5 @@ func (r *Runtime) RenumberLocks() error {
|
|||
}
|
||||
}
|
||||
|
||||
r.lock.Unlock()
|
||||
locked = false
|
||||
|
||||
return r.Shutdown(false)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue