diff options
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r-- | drivers/md/dm.c | 55 |
1 files changed, 15 insertions, 40 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 314a0e2faf79..e67a4be0080d 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -318,7 +318,6 @@ static void __exit dm_exit(void) | |||
318 | /* | 318 | /* |
319 | * Should be empty by this point. | 319 | * Should be empty by this point. |
320 | */ | 320 | */ |
321 | idr_remove_all(&_minor_idr); | ||
322 | idr_destroy(&_minor_idr); | 321 | idr_destroy(&_minor_idr); |
323 | } | 322 | } |
324 | 323 | ||
@@ -1756,62 +1755,38 @@ static void free_minor(int minor) | |||
1756 | */ | 1755 | */ |
1757 | static int specific_minor(int minor) | 1756 | static int specific_minor(int minor) |
1758 | { | 1757 | { |
1759 | int r, m; | 1758 | int r; |
1760 | 1759 | ||
1761 | if (minor >= (1 << MINORBITS)) | 1760 | if (minor >= (1 << MINORBITS)) |
1762 | return -EINVAL; | 1761 | return -EINVAL; |
1763 | 1762 | ||
1764 | r = idr_pre_get(&_minor_idr, GFP_KERNEL); | 1763 | idr_preload(GFP_KERNEL); |
1765 | if (!r) | ||
1766 | return -ENOMEM; | ||
1767 | |||
1768 | spin_lock(&_minor_lock); | 1764 | spin_lock(&_minor_lock); |
1769 | 1765 | ||
1770 | if (idr_find(&_minor_idr, minor)) { | 1766 | r = idr_alloc(&_minor_idr, MINOR_ALLOCED, minor, minor + 1, GFP_NOWAIT); |
1771 | r = -EBUSY; | ||
1772 | goto out; | ||
1773 | } | ||
1774 | |||
1775 | r = idr_get_new_above(&_minor_idr, MINOR_ALLOCED, minor, &m); | ||
1776 | if (r) | ||
1777 | goto out; | ||
1778 | 1767 | ||
1779 | if (m != minor) { | ||
1780 | idr_remove(&_minor_idr, m); | ||
1781 | r = -EBUSY; | ||
1782 | goto out; | ||
1783 | } | ||
1784 | |||
1785 | out: | ||
1786 | spin_unlock(&_minor_lock); | 1768 | spin_unlock(&_minor_lock); |
1787 | return r; | 1769 | idr_preload_end(); |
1770 | if (r < 0) | ||
1771 | return r == -ENOSPC ? -EBUSY : r; | ||
1772 | return 0; | ||
1788 | } | 1773 | } |
1789 | 1774 | ||
1790 | static int next_free_minor(int *minor) | 1775 | static int next_free_minor(int *minor) |
1791 | { | 1776 | { |
1792 | int r, m; | 1777 | int r; |
1793 | |||
1794 | r = idr_pre_get(&_minor_idr, GFP_KERNEL); | ||
1795 | if (!r) | ||
1796 | return -ENOMEM; | ||
1797 | 1778 | ||
1779 | idr_preload(GFP_KERNEL); | ||
1798 | spin_lock(&_minor_lock); | 1780 | spin_lock(&_minor_lock); |
1799 | 1781 | ||
1800 | r = idr_get_new(&_minor_idr, MINOR_ALLOCED, &m); | 1782 | r = idr_alloc(&_minor_idr, MINOR_ALLOCED, 0, 1 << MINORBITS, GFP_NOWAIT); |
1801 | if (r) | ||
1802 | goto out; | ||
1803 | |||
1804 | if (m >= (1 << MINORBITS)) { | ||
1805 | idr_remove(&_minor_idr, m); | ||
1806 | r = -ENOSPC; | ||
1807 | goto out; | ||
1808 | } | ||
1809 | |||
1810 | *minor = m; | ||
1811 | 1783 | ||
1812 | out: | ||
1813 | spin_unlock(&_minor_lock); | 1784 | spin_unlock(&_minor_lock); |
1814 | return r; | 1785 | idr_preload_end(); |
1786 | if (r < 0) | ||
1787 | return r; | ||
1788 | *minor = r; | ||
1789 | return 0; | ||
1815 | } | 1790 | } |
1816 | 1791 | ||
1817 | static const struct block_device_operations dm_blk_dops; | 1792 | static const struct block_device_operations dm_blk_dops; |