Recreate SHM locks when renumbering on count mismatch

When we're renumbering locks, we're destroying all existing
allocations anyways, so destroying the old lock struct is not a
particularly big deal. Existing long-lived libpod instances will
continue to use the old locks, but that will be solved in a
followon.

Also, solve an issue with returning error values in the C code.
There were a few places where we return ERRNO where it was not
set, so make them return actual error codes).

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
This commit is contained in:
Matthew Heon
2019-02-15 10:33:59 -05:00
parent a72025d6fd
commit f9c548219b
2 changed files with 24 additions and 8 deletions

View File

@ -203,6 +203,8 @@ shm_struct_t *setup_lock_shm(char *path, uint32_t num_locks, int *error_code) {
// terminating NULL byte. // terminating NULL byte.
// Returns a valid pointer on success or NULL on error. // Returns a valid pointer on success or NULL on error.
// If an error occurs, negative ERRNO values will be written to error_code. // If an error occurs, negative ERRNO values will be written to error_code.
// ERANGE is returned for a mismatch between num_locks and the number of locks
// available in the the SHM lock struct.
shm_struct_t *open_lock_shm(char *path, uint32_t num_locks, int *error_code) { shm_struct_t *open_lock_shm(char *path, uint32_t num_locks, int *error_code) {
int shm_fd; int shm_fd;
shm_struct_t *shm; shm_struct_t *shm;
@ -255,11 +257,11 @@ shm_struct_t *open_lock_shm(char *path, uint32_t num_locks, int *error_code) {
// Need to check the SHM to see if it's actually our locks // Need to check the SHM to see if it's actually our locks
if (shm->magic != MAGIC) { if (shm->magic != MAGIC) {
*error_code = -1 * errno; *error_code = -1 * EBADF;
goto CLEANUP; goto CLEANUP;
} }
if (shm->num_locks != (num_bitmaps * BITMAP_SIZE)) { if (shm->num_locks != (num_bitmaps * BITMAP_SIZE)) {
*error_code = -1 * errno; *error_code = -1 * ERANGE;
goto CLEANUP; goto CLEANUP;
} }

View File

@ -7,6 +7,7 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"sync" "sync"
"syscall"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
is "github.com/containers/image/storage" is "github.com/containers/image/storage"
@ -757,12 +758,6 @@ func makeRuntime(runtime *Runtime) (err error) {
aliveLock.Unlock() 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) _, err = os.Stat(runtimeAliveFile)
if err != nil { if err != nil {
@ -785,6 +780,18 @@ func makeRuntime(runtime *Runtime) (err error) {
manager, err := lock.OpenSHMLockManager(lockPath, runtime.config.NumLocks) manager, err := lock.OpenSHMLockManager(lockPath, runtime.config.NumLocks)
if err != nil { if err != nil {
if os.IsNotExist(errors.Cause(err)) { if os.IsNotExist(errors.Cause(err)) {
manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks)
if err != nil {
return err
}
} else if err == syscall.ERANGE && runtime.doRenumber {
// ERANGE indicates a lock numbering mismatch.
// Since we're renumbering, this is not fatal.
// Remove the earlier set of locks and recreate.
if err := os.Remove(filepath.Join("/dev/shm", lockPath)); err != nil {
return errors.Wrapf(err, "error removing libpod locks file %s", lockPath)
}
manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks) manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks)
if err != nil { if err != nil {
return err return err
@ -795,6 +802,13 @@ func makeRuntime(runtime *Runtime) (err error) {
} }
runtime.lockManager = manager runtime.lockManager = manager
// 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()
}
// If we need to refresh the state, do it now - things are guaranteed to // If we need to refresh the state, do it now - things are guaranteed to
// be set up by now. // be set up by now.
if doRefresh { if doRefresh {