diff options
-rw-r--r-- | libpod/options.go | 20 | ||||
-rw-r--r-- | libpod/runtime.go | 17 | ||||
-rw-r--r-- | libpod/runtime_renumber.go | 29 |
3 files changed, 37 insertions, 29 deletions
diff --git a/libpod/options.go b/libpod/options.go index 06737776b..4a3dd582d 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -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. diff --git a/libpod/runtime.go b/libpod/runtime.go index 4f5d1e292..bc7c061c4 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -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 diff --git a/libpod/runtime_renumber.go b/libpod/runtime_renumber.go index d5279934e..04abc84d1 100644 --- a/libpod/runtime_renumber.go +++ b/libpod/runtime_renumber.go @@ -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) } |