From 0f637e09da85b2aaefa279cfb571b004a2cc6d59 Mon Sep 17 00:00:00 2001
From: Matthew Heon <matthew.heon@pm.me>
Date: Wed, 11 Nov 2020 15:57:06 -0500
Subject: Ensure we do not double-lock the same volume in create

When making containers, we want to lock all named volumes we are
adding the container to, to ensure they aren't removed from under
us while we are working. Unfortunately, this code did not account
for a container having the same volume mounted in multiple places
so it could deadlock. Add a map to ensure that we don't lock the
same name more than once to resolve this.

Fixes #8221

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
---
 libpod/container_internal.go | 1 +
 libpod/runtime_ctr.go        | 7 +++++++
 2 files changed, 8 insertions(+)

(limited to 'libpod')

diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 0aeaae43d..3a8566760 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -1503,6 +1503,7 @@ func (c *Container) mountStorage() (_ string, deferredErr error) {
 // config.
 // Returns the volume that was mounted.
 func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string) (*Volume, error) {
+	logrus.Debugf("Going to mount named volume %s", v.Name)
 	vol, err := c.runtime.state.Volume(v.Name)
 	if err != nil {
 		return nil, errors.Wrapf(err, "error retrieving named volume %s for container %s", v.Name, c.ID())
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index c84268889..14b537ca2 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -345,8 +345,15 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
 
 	// Lock all named volumes we are adding ourself to, to ensure we can't
 	// use a volume being removed.
+	volsLocked := make(map[string]bool)
 	for _, namedVol := range ctrNamedVolumes {
 		toLock := namedVol
+		// Ensure that we don't double-lock a named volume that is used
+		// more than once.
+		if volsLocked[namedVol.Name()] {
+			continue
+		}
+		volsLocked[namedVol.Name()] = true
 		toLock.lock.Lock()
 		defer toLock.lock.Unlock()
 	}
-- 
cgit v1.2.3-54-g00ecf