diff options
author | NeilBrown <neilb@suse.de> | 2005-11-09 00:39:39 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-09 10:56:39 -0500 |
commit | 96de1e663cda65ba9275afb1bc007f34e5068ba1 (patch) | |
tree | b927dda4f0f2d2669658f5974a848d9f701f330b /drivers/md/raid5.c | |
parent | 3855ad9f398de88a3290f7dd799633c4b73903ea (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.c | 30 |
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 | |||
1746 | raid5_show_stripe_cache_size(mddev_t *mddev, char *page) | 1746 | raid5_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 | ||
1752 | static ssize_t | 1755 | static 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 | ||
1780 | static struct md_sysfs_entry raid5_stripecache_size = { | 1785 | static struct md_sysfs_entry |
1781 | .attr = {.name = "stripe_cache_size", .mode = S_IRUGO | S_IWUSR }, | 1786 | raid5_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 | ||
1786 | static ssize_t | 1790 | static ssize_t |
1787 | raid5_show_stripe_cache_active(mddev_t *mddev, char *page) | 1791 | stripe_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 | ||
1793 | static struct md_sysfs_entry raid5_stripecache_active = { | 1800 | static struct md_sysfs_entry |
1794 | .attr = {.name = "stripe_cache_active", .mode = S_IRUGO}, | 1801 | raid5_stripecache_active = __ATTR_RO(stripe_cache_active); |
1795 | .show = raid5_show_stripe_cache_active, | ||
1796 | }; | ||
1797 | 1802 | ||
1798 | static struct attribute *raid5_attrs[] = { | 1803 | static 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 | } |