static unsigned int major = 0;
 static unsigned int _major = 0;
 
+static DEFINE_SPINLOCK(_minor_lock);
 /*
  * One of these is allocated per bio.
  */
 /*-----------------------------------------------------------------
  * An IDR is used to keep track of allocated minor numbers.
  *---------------------------------------------------------------*/
-static DEFINE_MUTEX(_minor_lock);
 static DEFINE_IDR(_minor_idr);
 
 static void free_minor(unsigned int minor)
 {
-       mutex_lock(&_minor_lock);
+       spin_lock(&_minor_lock);
        idr_remove(&_minor_idr, minor);
-       mutex_unlock(&_minor_lock);
+       spin_unlock(&_minor_lock);
 }
 
 /*
        if (!r)
                return -ENOMEM;
 
-       mutex_lock(&_minor_lock);
+       spin_lock(&_minor_lock);
 
        if (idr_find(&_minor_idr, minor)) {
                r = -EBUSY;
        }
 
 out:
-       mutex_unlock(&_minor_lock);
+       spin_unlock(&_minor_lock);
        return r;
 }
 
        if (!r)
                return -ENOMEM;
 
-       mutex_lock(&_minor_lock);
+       spin_lock(&_minor_lock);
 
        r = idr_get_new(&_minor_idr, MINOR_ALLOCED, &m);
        if (r) {
        *minor = m;
 
 out:
-       mutex_unlock(&_minor_lock);
+       spin_unlock(&_minor_lock);
        return r;
 }
 
        init_waitqueue_head(&md->eventq);
 
        /* Populate the mapping, nobody knows we exist yet */
-       mutex_lock(&_minor_lock);
+       spin_lock(&_minor_lock);
        old_md = idr_replace(&_minor_idr, md, minor);
-       mutex_unlock(&_minor_lock);
+       spin_unlock(&_minor_lock);
 
        BUG_ON(old_md != MINOR_ALLOCED);
 
        if (MAJOR(dev) != _major || minor >= (1 << MINORBITS))
                return NULL;
 
-       mutex_lock(&_minor_lock);
+       spin_lock(&_minor_lock);
 
        md = idr_find(&_minor_idr, minor);
        if (md && (md == MINOR_ALLOCED || (dm_disk(md)->first_minor != minor)))
                md = NULL;
 
-       mutex_unlock(&_minor_lock);
+       spin_unlock(&_minor_lock);
 
        return md;
 }
 {
        struct dm_table *map;
 
-       if (atomic_dec_and_test(&md->holders)) {
+       if (atomic_dec_and_lock(&md->holders, &_minor_lock)) {
                map = dm_get_table(md);
-               mutex_lock(&_minor_lock);
                idr_replace(&_minor_idr, MINOR_ALLOCED, dm_disk(md)->first_minor);
-               mutex_unlock(&_minor_lock);
+               spin_unlock(&_minor_lock);
                if (!dm_suspended(md)) {
                        dm_table_presuspend_targets(map);
                        dm_table_postsuspend_targets(map);