aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid5.c
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 /drivers/md/raid5.c
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>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r--drivers/md/raid5.c30
1 files changed, 18 insertions, 12 deletions
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}