dm: fix add_disk() NULL pointer due to race with free_dev()
authorMike Snitzer <snitzer@redhat.com>
Mon, 23 Mar 2015 21:01:43 +0000 (17:01 -0400)
committerMike Snitzer <snitzer@redhat.com>
Mon, 23 Mar 2015 22:14:00 +0000 (18:14 -0400)
commit63a4f065ece613b6d575b538234375b0e9c23bbc
treee1a7896387c308886622e6b7edd3f5225873fa0f
parente5db29806b99ce2b2640d2e4d4fcb983cea115c5
dm: fix add_disk() NULL pointer due to race with free_dev()

Commit c4db59d31e39 ("fs: don't reassign dirty inodes to
default_backing_dev_info") exposed DM to a latent race in free_dev() vs
add_disk() in relation to management of the device's minor number.

Fix this by refactoring free_dev() to match cleanup order of the
alloc_dev() error path.  Move cleanup of the gendisk, queue, and bdev
to _before_ the cleanup of the idr managed minor number.

Also, purely due to cleanup that fell out during the free_dev() audit:
- adjust dm_blk_close() to access the gendisk's private_data under
  the _minor_lock spinlock.
- move __dm_destroy()'s dm_get_live_table() call out from under the
  _minor_lock spinlock.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1202449

Reported-by: Zdenek Kabelac <zkabelac@redhat.com>
Reported-by: Jeff Moyer <jmoyer@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
drivers/md/dm.c