diff options
author | Jens Axboe <axboe@kernel.dk> | 2011-10-19 08:30:42 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2011-10-19 08:30:42 -0400 |
commit | 5c04b426f2e8b46cfc7969a35b2631063a3c646c (patch) | |
tree | 2d27d9f5d2fe5d5e8fbc01a467ec58bcb50235c1 /drivers/block/loop.c | |
parent | 499337bb6511e665a236a6a947f819d98ea340c6 (diff) | |
parent | 899e3ee404961a90b828ad527573aaaac39f0ab1 (diff) |
Merge branch 'v3.1-rc10' into for-3.2/core
Conflicts:
block/blk-core.c
include/linux/blkdev.h
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block/loop.c')
-rw-r--r-- | drivers/block/loop.c | 297 |
1 files changed, 206 insertions, 91 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 8360239d553c..157ddcb9d0a5 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -75,11 +75,11 @@ | |||
75 | #include <linux/kthread.h> | 75 | #include <linux/kthread.h> |
76 | #include <linux/splice.h> | 76 | #include <linux/splice.h> |
77 | #include <linux/sysfs.h> | 77 | #include <linux/sysfs.h> |
78 | 78 | #include <linux/miscdevice.h> | |
79 | #include <asm/uaccess.h> | 79 | #include <asm/uaccess.h> |
80 | 80 | ||
81 | static LIST_HEAD(loop_devices); | 81 | static DEFINE_IDR(loop_index_idr); |
82 | static DEFINE_MUTEX(loop_devices_mutex); | 82 | static DEFINE_MUTEX(loop_index_mutex); |
83 | 83 | ||
84 | static int max_part; | 84 | static int max_part; |
85 | static int part_shift; | 85 | static int part_shift; |
@@ -721,17 +721,10 @@ static inline int is_loop_device(struct file *file) | |||
721 | static ssize_t loop_attr_show(struct device *dev, char *page, | 721 | static ssize_t loop_attr_show(struct device *dev, char *page, |
722 | ssize_t (*callback)(struct loop_device *, char *)) | 722 | ssize_t (*callback)(struct loop_device *, char *)) |
723 | { | 723 | { |
724 | struct loop_device *l, *lo = NULL; | 724 | struct gendisk *disk = dev_to_disk(dev); |
725 | 725 | struct loop_device *lo = disk->private_data; | |
726 | mutex_lock(&loop_devices_mutex); | ||
727 | list_for_each_entry(l, &loop_devices, lo_list) | ||
728 | if (disk_to_dev(l->lo_disk) == dev) { | ||
729 | lo = l; | ||
730 | break; | ||
731 | } | ||
732 | mutex_unlock(&loop_devices_mutex); | ||
733 | 726 | ||
734 | return lo ? callback(lo, page) : -EIO; | 727 | return callback(lo, page); |
735 | } | 728 | } |
736 | 729 | ||
737 | #define LOOP_ATTR_RO(_name) \ | 730 | #define LOOP_ATTR_RO(_name) \ |
@@ -749,10 +742,10 @@ static ssize_t loop_attr_backing_file_show(struct loop_device *lo, char *buf) | |||
749 | ssize_t ret; | 742 | ssize_t ret; |
750 | char *p = NULL; | 743 | char *p = NULL; |
751 | 744 | ||
752 | mutex_lock(&lo->lo_ctl_mutex); | 745 | spin_lock_irq(&lo->lo_lock); |
753 | if (lo->lo_backing_file) | 746 | if (lo->lo_backing_file) |
754 | p = d_path(&lo->lo_backing_file->f_path, buf, PAGE_SIZE - 1); | 747 | p = d_path(&lo->lo_backing_file->f_path, buf, PAGE_SIZE - 1); |
755 | mutex_unlock(&lo->lo_ctl_mutex); | 748 | spin_unlock_irq(&lo->lo_lock); |
756 | 749 | ||
757 | if (IS_ERR_OR_NULL(p)) | 750 | if (IS_ERR_OR_NULL(p)) |
758 | ret = PTR_ERR(p); | 751 | ret = PTR_ERR(p); |
@@ -1006,7 +999,9 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) | |||
1006 | 999 | ||
1007 | kthread_stop(lo->lo_thread); | 1000 | kthread_stop(lo->lo_thread); |
1008 | 1001 | ||
1002 | spin_lock_irq(&lo->lo_lock); | ||
1009 | lo->lo_backing_file = NULL; | 1003 | lo->lo_backing_file = NULL; |
1004 | spin_unlock_irq(&lo->lo_lock); | ||
1010 | 1005 | ||
1011 | loop_release_xfer(lo); | 1006 | loop_release_xfer(lo); |
1012 | lo->transfer = NULL; | 1007 | lo->transfer = NULL; |
@@ -1484,13 +1479,22 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode, | |||
1484 | 1479 | ||
1485 | static int lo_open(struct block_device *bdev, fmode_t mode) | 1480 | static int lo_open(struct block_device *bdev, fmode_t mode) |
1486 | { | 1481 | { |
1487 | struct loop_device *lo = bdev->bd_disk->private_data; | 1482 | struct loop_device *lo; |
1483 | int err = 0; | ||
1484 | |||
1485 | mutex_lock(&loop_index_mutex); | ||
1486 | lo = bdev->bd_disk->private_data; | ||
1487 | if (!lo) { | ||
1488 | err = -ENXIO; | ||
1489 | goto out; | ||
1490 | } | ||
1488 | 1491 | ||
1489 | mutex_lock(&lo->lo_ctl_mutex); | 1492 | mutex_lock(&lo->lo_ctl_mutex); |
1490 | lo->lo_refcnt++; | 1493 | lo->lo_refcnt++; |
1491 | mutex_unlock(&lo->lo_ctl_mutex); | 1494 | mutex_unlock(&lo->lo_ctl_mutex); |
1492 | 1495 | out: | |
1493 | return 0; | 1496 | mutex_unlock(&loop_index_mutex); |
1497 | return err; | ||
1494 | } | 1498 | } |
1495 | 1499 | ||
1496 | static int lo_release(struct gendisk *disk, fmode_t mode) | 1500 | static int lo_release(struct gendisk *disk, fmode_t mode) |
@@ -1556,40 +1560,71 @@ int loop_register_transfer(struct loop_func_table *funcs) | |||
1556 | return 0; | 1560 | return 0; |
1557 | } | 1561 | } |
1558 | 1562 | ||
1563 | static int unregister_transfer_cb(int id, void *ptr, void *data) | ||
1564 | { | ||
1565 | struct loop_device *lo = ptr; | ||
1566 | struct loop_func_table *xfer = data; | ||
1567 | |||
1568 | mutex_lock(&lo->lo_ctl_mutex); | ||
1569 | if (lo->lo_encryption == xfer) | ||
1570 | loop_release_xfer(lo); | ||
1571 | mutex_unlock(&lo->lo_ctl_mutex); | ||
1572 | return 0; | ||
1573 | } | ||
1574 | |||
1559 | int loop_unregister_transfer(int number) | 1575 | int loop_unregister_transfer(int number) |
1560 | { | 1576 | { |
1561 | unsigned int n = number; | 1577 | unsigned int n = number; |
1562 | struct loop_device *lo; | ||
1563 | struct loop_func_table *xfer; | 1578 | struct loop_func_table *xfer; |
1564 | 1579 | ||
1565 | if (n == 0 || n >= MAX_LO_CRYPT || (xfer = xfer_funcs[n]) == NULL) | 1580 | if (n == 0 || n >= MAX_LO_CRYPT || (xfer = xfer_funcs[n]) == NULL) |
1566 | return -EINVAL; | 1581 | return -EINVAL; |
1567 | 1582 | ||
1568 | xfer_funcs[n] = NULL; | 1583 | xfer_funcs[n] = NULL; |
1569 | 1584 | idr_for_each(&loop_index_idr, &unregister_transfer_cb, xfer); | |
1570 | list_for_each_entry(lo, &loop_devices, lo_list) { | ||
1571 | mutex_lock(&lo->lo_ctl_mutex); | ||
1572 | |||
1573 | if (lo->lo_encryption == xfer) | ||
1574 | loop_release_xfer(lo); | ||
1575 | |||
1576 | mutex_unlock(&lo->lo_ctl_mutex); | ||
1577 | } | ||
1578 | |||
1579 | return 0; | 1585 | return 0; |
1580 | } | 1586 | } |
1581 | 1587 | ||
1582 | EXPORT_SYMBOL(loop_register_transfer); | 1588 | EXPORT_SYMBOL(loop_register_transfer); |
1583 | EXPORT_SYMBOL(loop_unregister_transfer); | 1589 | EXPORT_SYMBOL(loop_unregister_transfer); |
1584 | 1590 | ||
1585 | static struct loop_device *loop_alloc(int i) | 1591 | static int loop_add(struct loop_device **l, int i) |
1586 | { | 1592 | { |
1587 | struct loop_device *lo; | 1593 | struct loop_device *lo; |
1588 | struct gendisk *disk; | 1594 | struct gendisk *disk; |
1595 | int err; | ||
1589 | 1596 | ||
1590 | lo = kzalloc(sizeof(*lo), GFP_KERNEL); | 1597 | lo = kzalloc(sizeof(*lo), GFP_KERNEL); |
1591 | if (!lo) | 1598 | if (!lo) { |
1599 | err = -ENOMEM; | ||
1592 | goto out; | 1600 | goto out; |
1601 | } | ||
1602 | |||
1603 | err = idr_pre_get(&loop_index_idr, GFP_KERNEL); | ||
1604 | if (err < 0) | ||
1605 | goto out_free_dev; | ||
1606 | |||
1607 | if (i >= 0) { | ||
1608 | int m; | ||
1609 | |||
1610 | /* create specific i in the index */ | ||
1611 | err = idr_get_new_above(&loop_index_idr, lo, i, &m); | ||
1612 | if (err >= 0 && i != m) { | ||
1613 | idr_remove(&loop_index_idr, m); | ||
1614 | err = -EEXIST; | ||
1615 | } | ||
1616 | } else if (i == -1) { | ||
1617 | int m; | ||
1618 | |||
1619 | /* get next free nr */ | ||
1620 | err = idr_get_new(&loop_index_idr, lo, &m); | ||
1621 | if (err >= 0) | ||
1622 | i = m; | ||
1623 | } else { | ||
1624 | err = -EINVAL; | ||
1625 | } | ||
1626 | if (err < 0) | ||
1627 | goto out_free_dev; | ||
1593 | 1628 | ||
1594 | lo->lo_queue = blk_alloc_queue(GFP_KERNEL); | 1629 | lo->lo_queue = blk_alloc_queue(GFP_KERNEL); |
1595 | if (!lo->lo_queue) | 1630 | if (!lo->lo_queue) |
@@ -1610,81 +1645,158 @@ static struct loop_device *loop_alloc(int i) | |||
1610 | disk->private_data = lo; | 1645 | disk->private_data = lo; |
1611 | disk->queue = lo->lo_queue; | 1646 | disk->queue = lo->lo_queue; |
1612 | sprintf(disk->disk_name, "loop%d", i); | 1647 | sprintf(disk->disk_name, "loop%d", i); |
1613 | return lo; | 1648 | add_disk(disk); |
1649 | *l = lo; | ||
1650 | return lo->lo_number; | ||
1614 | 1651 | ||
1615 | out_free_queue: | 1652 | out_free_queue: |
1616 | blk_cleanup_queue(lo->lo_queue); | 1653 | blk_cleanup_queue(lo->lo_queue); |
1617 | out_free_dev: | 1654 | out_free_dev: |
1618 | kfree(lo); | 1655 | kfree(lo); |
1619 | out: | 1656 | out: |
1620 | return NULL; | 1657 | return err; |
1621 | } | 1658 | } |
1622 | 1659 | ||
1623 | static void loop_free(struct loop_device *lo) | 1660 | static void loop_remove(struct loop_device *lo) |
1624 | { | 1661 | { |
1662 | del_gendisk(lo->lo_disk); | ||
1625 | blk_cleanup_queue(lo->lo_queue); | 1663 | blk_cleanup_queue(lo->lo_queue); |
1626 | put_disk(lo->lo_disk); | 1664 | put_disk(lo->lo_disk); |
1627 | list_del(&lo->lo_list); | ||
1628 | kfree(lo); | 1665 | kfree(lo); |
1629 | } | 1666 | } |
1630 | 1667 | ||
1631 | static struct loop_device *loop_init_one(int i) | 1668 | static int find_free_cb(int id, void *ptr, void *data) |
1669 | { | ||
1670 | struct loop_device *lo = ptr; | ||
1671 | struct loop_device **l = data; | ||
1672 | |||
1673 | if (lo->lo_state == Lo_unbound) { | ||
1674 | *l = lo; | ||
1675 | return 1; | ||
1676 | } | ||
1677 | return 0; | ||
1678 | } | ||
1679 | |||
1680 | static int loop_lookup(struct loop_device **l, int i) | ||
1632 | { | 1681 | { |
1633 | struct loop_device *lo; | 1682 | struct loop_device *lo; |
1683 | int ret = -ENODEV; | ||
1634 | 1684 | ||
1635 | list_for_each_entry(lo, &loop_devices, lo_list) { | 1685 | if (i < 0) { |
1636 | if (lo->lo_number == i) | 1686 | int err; |
1637 | return lo; | 1687 | |
1688 | err = idr_for_each(&loop_index_idr, &find_free_cb, &lo); | ||
1689 | if (err == 1) { | ||
1690 | *l = lo; | ||
1691 | ret = lo->lo_number; | ||
1692 | } | ||
1693 | goto out; | ||
1638 | } | 1694 | } |
1639 | 1695 | ||
1640 | lo = loop_alloc(i); | 1696 | /* lookup and return a specific i */ |
1697 | lo = idr_find(&loop_index_idr, i); | ||
1641 | if (lo) { | 1698 | if (lo) { |
1642 | add_disk(lo->lo_disk); | 1699 | *l = lo; |
1643 | list_add_tail(&lo->lo_list, &loop_devices); | 1700 | ret = lo->lo_number; |
1644 | } | 1701 | } |
1645 | return lo; | 1702 | out: |
1646 | } | 1703 | return ret; |
1647 | |||
1648 | static void loop_del_one(struct loop_device *lo) | ||
1649 | { | ||
1650 | del_gendisk(lo->lo_disk); | ||
1651 | loop_free(lo); | ||
1652 | } | 1704 | } |
1653 | 1705 | ||
1654 | static struct kobject *loop_probe(dev_t dev, int *part, void *data) | 1706 | static struct kobject *loop_probe(dev_t dev, int *part, void *data) |
1655 | { | 1707 | { |
1656 | struct loop_device *lo; | 1708 | struct loop_device *lo; |
1657 | struct kobject *kobj; | 1709 | struct kobject *kobj; |
1710 | int err; | ||
1658 | 1711 | ||
1659 | mutex_lock(&loop_devices_mutex); | 1712 | mutex_lock(&loop_index_mutex); |
1660 | lo = loop_init_one(MINOR(dev) >> part_shift); | 1713 | err = loop_lookup(&lo, MINOR(dev) >> part_shift); |
1661 | kobj = lo ? get_disk(lo->lo_disk) : ERR_PTR(-ENOMEM); | 1714 | if (err < 0) |
1662 | mutex_unlock(&loop_devices_mutex); | 1715 | err = loop_add(&lo, MINOR(dev) >> part_shift); |
1716 | if (err < 0) | ||
1717 | kobj = ERR_PTR(err); | ||
1718 | else | ||
1719 | kobj = get_disk(lo->lo_disk); | ||
1720 | mutex_unlock(&loop_index_mutex); | ||
1663 | 1721 | ||
1664 | *part = 0; | 1722 | *part = 0; |
1665 | return kobj; | 1723 | return kobj; |
1666 | } | 1724 | } |
1667 | 1725 | ||
1726 | static long loop_control_ioctl(struct file *file, unsigned int cmd, | ||
1727 | unsigned long parm) | ||
1728 | { | ||
1729 | struct loop_device *lo; | ||
1730 | int ret = -ENOSYS; | ||
1731 | |||
1732 | mutex_lock(&loop_index_mutex); | ||
1733 | switch (cmd) { | ||
1734 | case LOOP_CTL_ADD: | ||
1735 | ret = loop_lookup(&lo, parm); | ||
1736 | if (ret >= 0) { | ||
1737 | ret = -EEXIST; | ||
1738 | break; | ||
1739 | } | ||
1740 | ret = loop_add(&lo, parm); | ||
1741 | break; | ||
1742 | case LOOP_CTL_REMOVE: | ||
1743 | ret = loop_lookup(&lo, parm); | ||
1744 | if (ret < 0) | ||
1745 | break; | ||
1746 | mutex_lock(&lo->lo_ctl_mutex); | ||
1747 | if (lo->lo_state != Lo_unbound) { | ||
1748 | ret = -EBUSY; | ||
1749 | mutex_unlock(&lo->lo_ctl_mutex); | ||
1750 | break; | ||
1751 | } | ||
1752 | if (lo->lo_refcnt > 0) { | ||
1753 | ret = -EBUSY; | ||
1754 | mutex_unlock(&lo->lo_ctl_mutex); | ||
1755 | break; | ||
1756 | } | ||
1757 | lo->lo_disk->private_data = NULL; | ||
1758 | mutex_unlock(&lo->lo_ctl_mutex); | ||
1759 | idr_remove(&loop_index_idr, lo->lo_number); | ||
1760 | loop_remove(lo); | ||
1761 | break; | ||
1762 | case LOOP_CTL_GET_FREE: | ||
1763 | ret = loop_lookup(&lo, -1); | ||
1764 | if (ret >= 0) | ||
1765 | break; | ||
1766 | ret = loop_add(&lo, -1); | ||
1767 | } | ||
1768 | mutex_unlock(&loop_index_mutex); | ||
1769 | |||
1770 | return ret; | ||
1771 | } | ||
1772 | |||
1773 | static const struct file_operations loop_ctl_fops = { | ||
1774 | .open = nonseekable_open, | ||
1775 | .unlocked_ioctl = loop_control_ioctl, | ||
1776 | .compat_ioctl = loop_control_ioctl, | ||
1777 | .owner = THIS_MODULE, | ||
1778 | .llseek = noop_llseek, | ||
1779 | }; | ||
1780 | |||
1781 | static struct miscdevice loop_misc = { | ||
1782 | .minor = LOOP_CTRL_MINOR, | ||
1783 | .name = "loop-control", | ||
1784 | .fops = &loop_ctl_fops, | ||
1785 | }; | ||
1786 | |||
1787 | MODULE_ALIAS_MISCDEV(LOOP_CTRL_MINOR); | ||
1788 | MODULE_ALIAS("devname:loop-control"); | ||
1789 | |||
1668 | static int __init loop_init(void) | 1790 | static int __init loop_init(void) |
1669 | { | 1791 | { |
1670 | int i, nr; | 1792 | int i, nr; |
1671 | unsigned long range; | 1793 | unsigned long range; |
1672 | struct loop_device *lo, *next; | 1794 | struct loop_device *lo; |
1795 | int err; | ||
1673 | 1796 | ||
1674 | /* | 1797 | err = misc_register(&loop_misc); |
1675 | * loop module now has a feature to instantiate underlying device | 1798 | if (err < 0) |
1676 | * structure on-demand, provided that there is an access dev node. | 1799 | return err; |
1677 | * However, this will not work well with user space tool that doesn't | ||
1678 | * know about such "feature". In order to not break any existing | ||
1679 | * tool, we do the following: | ||
1680 | * | ||
1681 | * (1) if max_loop is specified, create that many upfront, and this | ||
1682 | * also becomes a hard limit. | ||
1683 | * (2) if max_loop is not specified, create 8 loop device on module | ||
1684 | * load, user can further extend loop device by create dev node | ||
1685 | * themselves and have kernel automatically instantiate actual | ||
1686 | * device on-demand. | ||
1687 | */ | ||
1688 | 1800 | ||
1689 | part_shift = 0; | 1801 | part_shift = 0; |
1690 | if (max_part > 0) { | 1802 | if (max_part > 0) { |
@@ -1707,57 +1819,60 @@ static int __init loop_init(void) | |||
1707 | if (max_loop > 1UL << (MINORBITS - part_shift)) | 1819 | if (max_loop > 1UL << (MINORBITS - part_shift)) |
1708 | return -EINVAL; | 1820 | return -EINVAL; |
1709 | 1821 | ||
1822 | /* | ||
1823 | * If max_loop is specified, create that many devices upfront. | ||
1824 | * This also becomes a hard limit. If max_loop is not specified, | ||
1825 | * create CONFIG_BLK_DEV_LOOP_MIN_COUNT loop devices at module | ||
1826 | * init time. Loop devices can be requested on-demand with the | ||
1827 | * /dev/loop-control interface, or be instantiated by accessing | ||
1828 | * a 'dead' device node. | ||
1829 | */ | ||
1710 | if (max_loop) { | 1830 | if (max_loop) { |
1711 | nr = max_loop; | 1831 | nr = max_loop; |
1712 | range = max_loop << part_shift; | 1832 | range = max_loop << part_shift; |
1713 | } else { | 1833 | } else { |
1714 | nr = 8; | 1834 | nr = CONFIG_BLK_DEV_LOOP_MIN_COUNT; |
1715 | range = 1UL << MINORBITS; | 1835 | range = 1UL << MINORBITS; |
1716 | } | 1836 | } |
1717 | 1837 | ||
1718 | if (register_blkdev(LOOP_MAJOR, "loop")) | 1838 | if (register_blkdev(LOOP_MAJOR, "loop")) |
1719 | return -EIO; | 1839 | return -EIO; |
1720 | 1840 | ||
1721 | for (i = 0; i < nr; i++) { | ||
1722 | lo = loop_alloc(i); | ||
1723 | if (!lo) | ||
1724 | goto Enomem; | ||
1725 | list_add_tail(&lo->lo_list, &loop_devices); | ||
1726 | } | ||
1727 | |||
1728 | /* point of no return */ | ||
1729 | |||
1730 | list_for_each_entry(lo, &loop_devices, lo_list) | ||
1731 | add_disk(lo->lo_disk); | ||
1732 | |||
1733 | blk_register_region(MKDEV(LOOP_MAJOR, 0), range, | 1841 | blk_register_region(MKDEV(LOOP_MAJOR, 0), range, |
1734 | THIS_MODULE, loop_probe, NULL, NULL); | 1842 | THIS_MODULE, loop_probe, NULL, NULL); |
1735 | 1843 | ||
1844 | /* pre-create number of devices given by config or max_loop */ | ||
1845 | mutex_lock(&loop_index_mutex); | ||
1846 | for (i = 0; i < nr; i++) | ||
1847 | loop_add(&lo, i); | ||
1848 | mutex_unlock(&loop_index_mutex); | ||
1849 | |||
1736 | printk(KERN_INFO "loop: module loaded\n"); | 1850 | printk(KERN_INFO "loop: module loaded\n"); |
1737 | return 0; | 1851 | return 0; |
1852 | } | ||
1738 | 1853 | ||
1739 | Enomem: | 1854 | static int loop_exit_cb(int id, void *ptr, void *data) |
1740 | printk(KERN_INFO "loop: out of memory\n"); | 1855 | { |
1741 | 1856 | struct loop_device *lo = ptr; | |
1742 | list_for_each_entry_safe(lo, next, &loop_devices, lo_list) | ||
1743 | loop_free(lo); | ||
1744 | 1857 | ||
1745 | unregister_blkdev(LOOP_MAJOR, "loop"); | 1858 | loop_remove(lo); |
1746 | return -ENOMEM; | 1859 | return 0; |
1747 | } | 1860 | } |
1748 | 1861 | ||
1749 | static void __exit loop_exit(void) | 1862 | static void __exit loop_exit(void) |
1750 | { | 1863 | { |
1751 | unsigned long range; | 1864 | unsigned long range; |
1752 | struct loop_device *lo, *next; | ||
1753 | 1865 | ||
1754 | range = max_loop ? max_loop << part_shift : 1UL << MINORBITS; | 1866 | range = max_loop ? max_loop << part_shift : 1UL << MINORBITS; |
1755 | 1867 | ||
1756 | list_for_each_entry_safe(lo, next, &loop_devices, lo_list) | 1868 | idr_for_each(&loop_index_idr, &loop_exit_cb, NULL); |
1757 | loop_del_one(lo); | 1869 | idr_remove_all(&loop_index_idr); |
1870 | idr_destroy(&loop_index_idr); | ||
1758 | 1871 | ||
1759 | blk_unregister_region(MKDEV(LOOP_MAJOR, 0), range); | 1872 | blk_unregister_region(MKDEV(LOOP_MAJOR, 0), range); |
1760 | unregister_blkdev(LOOP_MAJOR, "loop"); | 1873 | unregister_blkdev(LOOP_MAJOR, "loop"); |
1874 | |||
1875 | misc_deregister(&loop_misc); | ||
1761 | } | 1876 | } |
1762 | 1877 | ||
1763 | module_init(loop_init); | 1878 | module_init(loop_init); |