aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2005-11-09 00:39:39 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-09 10:56:39 -0500
commit96de1e663cda65ba9275afb1bc007f34e5068ba1 (patch)
treeb927dda4f0f2d2669658f5974a848d9f701f330b
parent3855ad9f398de88a3290f7dd799633c4b73903ea (diff)
[PATCH] md: fix some locking and module refcounting issues with md's use of sysfs
1/ I really should be using the __ATTR macros for defining attributes, so that the .owner field get set properly, otherwise modules can be removed while sysfs files are open. This also involves some name changes of _show routines. 2/ Always lock the mddev (against reconfiguration) for all sysfs attribute access. This easily avoid certain races and is completely consistant with other interfaces (ioctl and /proc/mdstat both always lock against reconfiguration). 3/ raid5 attributes must check that the 'conf' structure actually exists (the array could have been stopped while an attribute file was open). 4/ A missing 'kfree' from when the raid5_conf_t was converted to have a kobject embedded, and then converted back again. Signed-off-by: Neil Brown <neilb@suse.de> Acked-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/md/md.c62
-rw-r--r--drivers/md/raid5.c30
2 files changed, 46 insertions, 46 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 2b5928976095..b2d8813ed716 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1504,7 +1504,7 @@ struct rdev_sysfs_entry {
1504}; 1504};
1505 1505
1506static ssize_t 1506static ssize_t
1507rdev_show_state(mdk_rdev_t *rdev, char *page) 1507state_show(mdk_rdev_t *rdev, char *page)
1508{ 1508{
1509 char *sep = ""; 1509 char *sep = "";
1510 int len=0; 1510 int len=0;
@@ -1525,13 +1525,11 @@ rdev_show_state(mdk_rdev_t *rdev, char *page)
1525 return len+sprintf(page+len, "\n"); 1525 return len+sprintf(page+len, "\n");
1526} 1526}
1527 1527
1528static struct rdev_sysfs_entry rdev_state = { 1528static struct rdev_sysfs_entry
1529 .attr = {.name = "state", .mode = S_IRUGO }, 1529rdev_state = __ATTR_RO(state);
1530 .show = rdev_show_state,
1531};
1532 1530
1533static ssize_t 1531static ssize_t
1534rdev_show_super(mdk_rdev_t *rdev, char *page) 1532super_show(mdk_rdev_t *rdev, char *page)
1535{ 1533{
1536 if (rdev->sb_loaded && rdev->sb_size) { 1534 if (rdev->sb_loaded && rdev->sb_size) {
1537 memcpy(page, page_address(rdev->sb_page), rdev->sb_size); 1535 memcpy(page, page_address(rdev->sb_page), rdev->sb_size);
@@ -1539,10 +1537,8 @@ rdev_show_super(mdk_rdev_t *rdev, char *page)
1539 } else 1537 } else
1540 return 0; 1538 return 0;
1541} 1539}
1542static struct rdev_sysfs_entry rdev_super = { 1540static struct rdev_sysfs_entry rdev_super = __ATTR_RO(super);
1543 .attr = {.name = "super", .mode = S_IRUGO }, 1541
1544 .show = rdev_show_super,
1545};
1546static struct attribute *rdev_default_attrs[] = { 1542static struct attribute *rdev_default_attrs[] = {
1547 &rdev_state.attr, 1543 &rdev_state.attr,
1548 &rdev_super.attr, 1544 &rdev_super.attr,
@@ -1728,7 +1724,7 @@ static void analyze_sbs(mddev_t * mddev)
1728} 1724}
1729 1725
1730static ssize_t 1726static ssize_t
1731md_show_level(mddev_t *mddev, char *page) 1727level_show(mddev_t *mddev, char *page)
1732{ 1728{
1733 mdk_personality_t *p = mddev->pers; 1729 mdk_personality_t *p = mddev->pers;
1734 if (p == NULL) 1730 if (p == NULL)
@@ -1739,21 +1735,15 @@ md_show_level(mddev_t *mddev, char *page)
1739 return sprintf(page, "%s\n", p->name); 1735 return sprintf(page, "%s\n", p->name);
1740} 1736}
1741 1737
1742static struct md_sysfs_entry md_level = { 1738static struct md_sysfs_entry md_level = __ATTR_RO(level);
1743 .attr = {.name = "level", .mode = S_IRUGO },
1744 .show = md_show_level,
1745};
1746 1739
1747static ssize_t 1740static ssize_t
1748md_show_rdisks(mddev_t *mddev, char *page) 1741raid_disks_show(mddev_t *mddev, char *page)
1749{ 1742{
1750 return sprintf(page, "%d\n", mddev->raid_disks); 1743 return sprintf(page, "%d\n", mddev->raid_disks);
1751} 1744}
1752 1745
1753static struct md_sysfs_entry md_raid_disks = { 1746static struct md_sysfs_entry md_raid_disks = __ATTR_RO(raid_disks);
1754 .attr = {.name = "raid_disks", .mode = S_IRUGO },
1755 .show = md_show_rdisks,
1756};
1757 1747
1758static ssize_t 1748static ssize_t
1759md_show_scan(mddev_t *mddev, char *page) 1749md_show_scan(mddev_t *mddev, char *page)
@@ -1782,10 +1772,10 @@ md_store_scan(mddev_t *mddev, const char *page, size_t len)
1782 if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || 1772 if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
1783 test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) 1773 test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
1784 return -EBUSY; 1774 return -EBUSY;
1785 down(&mddev->reconfig_sem); 1775
1786 if (mddev->pers && mddev->pers->sync_request) 1776 if (mddev->pers && mddev->pers->sync_request)
1787 canscan=1; 1777 canscan=1;
1788 up(&mddev->reconfig_sem); 1778
1789 if (!canscan) 1779 if (!canscan)
1790 return -EINVAL; 1780 return -EINVAL;
1791 1781
@@ -1801,22 +1791,18 @@ md_store_scan(mddev_t *mddev, const char *page, size_t len)
1801} 1791}
1802 1792
1803static ssize_t 1793static ssize_t
1804md_show_mismatch(mddev_t *mddev, char *page) 1794mismatch_cnt_show(mddev_t *mddev, char *page)
1805{ 1795{
1806 return sprintf(page, "%llu\n", 1796 return sprintf(page, "%llu\n",
1807 (unsigned long long) mddev->resync_mismatches); 1797 (unsigned long long) mddev->resync_mismatches);
1808} 1798}
1809 1799
1810static struct md_sysfs_entry md_scan_mode = { 1800static struct md_sysfs_entry
1811 .attr = {.name = "scan_mode", .mode = S_IRUGO|S_IWUSR }, 1801md_scan_mode = __ATTR(scan_mode, S_IRUGO|S_IWUSR, md_show_scan, md_store_scan);
1812 .show = md_show_scan,
1813 .store = md_store_scan,
1814};
1815 1802
1816static struct md_sysfs_entry md_mismatches = { 1803
1817 .attr = {.name = "mismatch_cnt", .mode = S_IRUGO }, 1804static struct md_sysfs_entry
1818 .show = md_show_mismatch, 1805md_mismatches = __ATTR_RO(mismatch_cnt);
1819};
1820 1806
1821static struct attribute *md_default_attrs[] = { 1807static struct attribute *md_default_attrs[] = {
1822 &md_level.attr, 1808 &md_level.attr,
@@ -1831,10 +1817,14 @@ md_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
1831{ 1817{
1832 struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr); 1818 struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr);
1833 mddev_t *mddev = container_of(kobj, struct mddev_s, kobj); 1819 mddev_t *mddev = container_of(kobj, struct mddev_s, kobj);
1820 ssize_t rv;
1834 1821
1835 if (!entry->show) 1822 if (!entry->show)
1836 return -EIO; 1823 return -EIO;
1837 return entry->show(mddev, page); 1824 mddev_lock(mddev);
1825 rv = entry->show(mddev, page);
1826 mddev_unlock(mddev);
1827 return rv;
1838} 1828}
1839 1829
1840static ssize_t 1830static ssize_t
@@ -1843,10 +1833,14 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
1843{ 1833{
1844 struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr); 1834 struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr);
1845 mddev_t *mddev = container_of(kobj, struct mddev_s, kobj); 1835 mddev_t *mddev = container_of(kobj, struct mddev_s, kobj);
1836 ssize_t rv;
1846 1837
1847 if (!entry->store) 1838 if (!entry->store)
1848 return -EIO; 1839 return -EIO;
1849 return entry->store(mddev, page, length); 1840 mddev_lock(mddev);
1841 rv = entry->store(mddev, page, length);
1842 mddev_unlock(mddev);
1843 return rv;
1850} 1844}
1851 1845
1852static void md_free(struct kobject *ko) 1846static void md_free(struct kobject *ko)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 51003b008de7..e2a40283e323 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1746,7 +1746,10 @@ static ssize_t
1746raid5_show_stripe_cache_size(mddev_t *mddev, char *page) 1746raid5_show_stripe_cache_size(mddev_t *mddev, char *page)
1747{ 1747{
1748 raid5_conf_t *conf = mddev_to_conf(mddev); 1748 raid5_conf_t *conf = mddev_to_conf(mddev);
1749 return sprintf(page, "%d\n", conf->max_nr_stripes); 1749 if (conf)
1750 return sprintf(page, "%d\n", conf->max_nr_stripes);
1751 else
1752 return 0;
1750} 1753}
1751 1754
1752static ssize_t 1755static ssize_t
@@ -1757,6 +1760,8 @@ raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
1757 int new; 1760 int new;
1758 if (len >= PAGE_SIZE) 1761 if (len >= PAGE_SIZE)
1759 return -EINVAL; 1762 return -EINVAL;
1763 if (!conf)
1764 return -ENODEV;
1760 1765
1761 new = simple_strtoul(page, &end, 10); 1766 new = simple_strtoul(page, &end, 10);
1762 if (!*page || (*end && *end != '\n') ) 1767 if (!*page || (*end && *end != '\n') )
@@ -1777,23 +1782,23 @@ raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
1777 return len; 1782 return len;
1778} 1783}
1779 1784
1780static struct md_sysfs_entry raid5_stripecache_size = { 1785static struct md_sysfs_entry
1781 .attr = {.name = "stripe_cache_size", .mode = S_IRUGO | S_IWUSR }, 1786raid5_stripecache_size = __ATTR(stripe_cache_size, S_IRUGO | S_IWUSR,
1782 .show = raid5_show_stripe_cache_size, 1787 raid5_show_stripe_cache_size,
1783 .store = raid5_store_stripe_cache_size, 1788 raid5_store_stripe_cache_size);
1784};
1785 1789
1786static ssize_t 1790static ssize_t
1787raid5_show_stripe_cache_active(mddev_t *mddev, char *page) 1791stripe_cache_active_show(mddev_t *mddev, char *page)
1788{ 1792{
1789 raid5_conf_t *conf = mddev_to_conf(mddev); 1793 raid5_conf_t *conf = mddev_to_conf(mddev);
1790 return sprintf(page, "%d\n", atomic_read(&conf->active_stripes)); 1794 if (conf)
1795 return sprintf(page, "%d\n", atomic_read(&conf->active_stripes));
1796 else
1797 return 0;
1791} 1798}
1792 1799
1793static struct md_sysfs_entry raid5_stripecache_active = { 1800static struct md_sysfs_entry
1794 .attr = {.name = "stripe_cache_active", .mode = S_IRUGO}, 1801raid5_stripecache_active = __ATTR_RO(stripe_cache_active);
1795 .show = raid5_show_stripe_cache_active,
1796};
1797 1802
1798static struct attribute *raid5_attrs[] = { 1803static struct attribute *raid5_attrs[] = {
1799 &raid5_stripecache_size.attr, 1804 &raid5_stripecache_size.attr,
@@ -1981,6 +1986,7 @@ static int stop(mddev_t *mddev)
1981 free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); 1986 free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER);
1982 blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ 1987 blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
1983 sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); 1988 sysfs_remove_group(&mddev->kobj, &raid5_attrs_group);
1989 kfree(conf);
1984 mddev->private = NULL; 1990 mddev->private = NULL;
1985 return 0; 1991 return 0;
1986} 1992}