dotcloud/docker — pull request #4951 by alexlarsson (2014-04-01 09:42:28+00:00)
Title: Fix AB-BA deadlock in devicemapper backend

We currently drop the global lock while holding a per-device lock when we are e.g sleeping for device removal, and then we re-aquire it when the sleep is done. This is causing a AB-BA deadlock if anyone at the same time tries to do any operation on that device like this:
```
thread A: thread B
grabs global lock
grabs device lock
releases global lock
sleeps
grabs global lock
blocks on device lock
wakes up
blocks on global lock
```
To trigger this you can for instance do:

```
ID=`docker run -d fedora sleep 5`
cd /var/lib/docker/devicemapper/mnt/$ID
docker wait $ID
docker rm $ID &
docker rm $ID
```

The unmount will fail due to the mount being busy thus causing the timeout and the second rm will then trigger the deadlock.

This series of commit fixes this by first cleaning up the use of the Devices map, then introducing a separate lock for it so that it can be accessed independently of the global lock. Then we define (and use) a lock ordering such that the device locks are always grabbed before the global lock.