aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/raid5.c183
-rw-r--r--include/linux/raid/raid5.h1
2 files changed, 152 insertions, 32 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 8cf1ae8b8a71..121fbaa9ed59 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -293,9 +293,31 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
293 return sh; 293 return sh;
294} 294}
295 295
296static int grow_stripes(raid5_conf_t *conf, int num) 296static int grow_one_stripe(raid5_conf_t *conf)
297{ 297{
298 struct stripe_head *sh; 298 struct stripe_head *sh;
299 sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
300 if (!sh)
301 return 0;
302 memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
303 sh->raid_conf = conf;
304 spin_lock_init(&sh->lock);
305
306 if (grow_buffers(sh, conf->raid_disks)) {
307 shrink_buffers(sh, conf->raid_disks);
308 kmem_cache_free(conf->slab_cache, sh);
309 return 0;
310 }
311 /* we just created an active stripe so... */
312 atomic_set(&sh->count, 1);
313 atomic_inc(&conf->active_stripes);
314 INIT_LIST_HEAD(&sh->lru);
315 release_stripe(sh);
316 return 1;
317}
318
319static int grow_stripes(raid5_conf_t *conf, int num)
320{
299 kmem_cache_t *sc; 321 kmem_cache_t *sc;
300 int devs = conf->raid_disks; 322 int devs = conf->raid_disks;
301 323
@@ -308,43 +330,34 @@ static int grow_stripes(raid5_conf_t *conf, int num)
308 return 1; 330 return 1;
309 conf->slab_cache = sc; 331 conf->slab_cache = sc;
310 while (num--) { 332 while (num--) {
311 sh = kmem_cache_alloc(sc, GFP_KERNEL); 333 if (!grow_one_stripe(conf))
312 if (!sh)
313 return 1;
314 memset(sh, 0, sizeof(*sh) + (devs-1)*sizeof(struct r5dev));
315 sh->raid_conf = conf;
316 spin_lock_init(&sh->lock);
317
318 if (grow_buffers(sh, conf->raid_disks)) {
319 shrink_buffers(sh, conf->raid_disks);
320 kmem_cache_free(sc, sh);
321 return 1; 334 return 1;
322 }
323 /* we just created an active stripe so... */
324 atomic_set(&sh->count, 1);
325 atomic_inc(&conf->active_stripes);
326 INIT_LIST_HEAD(&sh->lru);
327 release_stripe(sh);
328 } 335 }
329 return 0; 336 return 0;
330} 337}
331 338
332static void shrink_stripes(raid5_conf_t *conf) 339static int drop_one_stripe(raid5_conf_t *conf)
333{ 340{
334 struct stripe_head *sh; 341 struct stripe_head *sh;
335 342
336 while (1) { 343 spin_lock_irq(&conf->device_lock);
337 spin_lock_irq(&conf->device_lock); 344 sh = get_free_stripe(conf);
338 sh = get_free_stripe(conf); 345 spin_unlock_irq(&conf->device_lock);
339 spin_unlock_irq(&conf->device_lock); 346 if (!sh)
340 if (!sh) 347 return 0;
341 break; 348 if (atomic_read(&sh->count))
342 if (atomic_read(&sh->count)) 349 BUG();
343 BUG(); 350 shrink_buffers(sh, conf->raid_disks);
344 shrink_buffers(sh, conf->raid_disks); 351 kmem_cache_free(conf->slab_cache, sh);
345 kmem_cache_free(conf->slab_cache, sh); 352 atomic_dec(&conf->active_stripes);
346 atomic_dec(&conf->active_stripes); 353 return 1;
347 } 354}
355
356static void shrink_stripes(raid5_conf_t *conf)
357{
358 while (drop_one_stripe(conf))
359 ;
360
348 kmem_cache_destroy(conf->slab_cache); 361 kmem_cache_destroy(conf->slab_cache);
349 conf->slab_cache = NULL; 362 conf->slab_cache = NULL;
350} 363}
@@ -1714,6 +1727,108 @@ static void raid5d (mddev_t *mddev)
1714 PRINTK("--- raid5d inactive\n"); 1727 PRINTK("--- raid5d inactive\n");
1715} 1728}
1716 1729
1730struct raid5_sysfs_entry {
1731 struct attribute attr;
1732 ssize_t (*show)(raid5_conf_t *, char *);
1733 ssize_t (*store)(raid5_conf_t *, const char *, ssize_t);
1734};
1735
1736static ssize_t
1737raid5_show_stripe_cache_size(raid5_conf_t *conf, char *page)
1738{
1739 return sprintf(page, "%d\n", conf->max_nr_stripes);
1740}
1741
1742static ssize_t
1743raid5_store_stripe_cache_size(raid5_conf_t *conf, const char *page, ssize_t len)
1744{
1745 char *end;
1746 int new;
1747 if (len >= PAGE_SIZE)
1748 return -EINVAL;
1749
1750 new = simple_strtoul(page, &end, 10);
1751 if (!*page || (*end && *end != '\n') )
1752 return -EINVAL;
1753 if (new <= 16 || new > 32768)
1754 return -EINVAL;
1755 while (new < conf->max_nr_stripes) {
1756 if (drop_one_stripe(conf))
1757 conf->max_nr_stripes--;
1758 else
1759 break;
1760 }
1761 while (new > conf->max_nr_stripes) {
1762 if (grow_one_stripe(conf))
1763 conf->max_nr_stripes++;
1764 else break;
1765 }
1766 return len;
1767}
1768static struct raid5_sysfs_entry raid5_stripecache_size = {
1769 .attr = {.name = "stripe_cache_size", .mode = S_IRUGO | S_IWUSR },
1770 .show = raid5_show_stripe_cache_size,
1771 .store = raid5_store_stripe_cache_size,
1772};
1773
1774static ssize_t
1775raid5_show_stripe_cache_active(raid5_conf_t *conf, char *page)
1776{
1777 return sprintf(page, "%d\n", atomic_read(&conf->active_stripes));
1778}
1779
1780static struct raid5_sysfs_entry raid5_stripecache_active = {
1781 .attr = {.name = "stripe_cache_active", .mode = S_IRUGO},
1782 .show = raid5_show_stripe_cache_active,
1783};
1784
1785static struct attribute *raid5_default_attrs[] = {
1786 &raid5_stripecache_size.attr,
1787 &raid5_stripecache_active.attr,
1788 NULL,
1789};
1790
1791static ssize_t
1792raid5_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
1793{
1794 struct raid5_sysfs_entry *entry = container_of(attr, struct raid5_sysfs_entry, attr);
1795 raid5_conf_t *conf = container_of(kobj, raid5_conf_t, kobj);
1796
1797 if (!entry->show)
1798 return -EIO;
1799 return entry->show(conf, page);
1800}
1801
1802static ssize_t
1803raid5_attr_store(struct kobject *kobj, struct attribute *attr,
1804 const char *page, size_t length)
1805{
1806 struct raid5_sysfs_entry *entry = container_of(attr, struct raid5_sysfs_entry, attr);
1807 raid5_conf_t *conf = container_of(kobj, raid5_conf_t, kobj);
1808
1809 if (!entry->store)
1810 return -EIO;
1811 return entry->store(conf, page, length);
1812}
1813
1814static void raid5_free(struct kobject *ko)
1815{
1816 raid5_conf_t *conf = container_of(ko, raid5_conf_t, kobj);
1817 kfree(conf);
1818}
1819
1820
1821static struct sysfs_ops raid5_sysfs_ops = {
1822 .show = raid5_attr_show,
1823 .store = raid5_attr_store,
1824};
1825
1826static struct kobj_type raid5_ktype = {
1827 .release = raid5_free,
1828 .sysfs_ops = &raid5_sysfs_ops,
1829 .default_attrs = raid5_default_attrs,
1830};
1831
1717static int run(mddev_t *mddev) 1832static int run(mddev_t *mddev)
1718{ 1833{
1719 raid5_conf_t *conf; 1834 raid5_conf_t *conf;
@@ -1855,6 +1970,10 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
1855 } 1970 }
1856 1971
1857 /* Ok, everything is just fine now */ 1972 /* Ok, everything is just fine now */
1973 conf->kobj.parent = kobject_get(&mddev->kobj);
1974 strcpy(conf->kobj.name, "raid5");
1975 conf->kobj.ktype = &raid5_ktype;
1976 kobject_register(&conf->kobj);
1858 1977
1859 if (mddev->bitmap) 1978 if (mddev->bitmap)
1860 mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ; 1979 mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
@@ -1879,7 +1998,7 @@ abort:
1879 1998
1880 1999
1881 2000
1882static int stop (mddev_t *mddev) 2001static int stop(mddev_t *mddev)
1883{ 2002{
1884 raid5_conf_t *conf = (raid5_conf_t *) mddev->private; 2003 raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
1885 2004
@@ -1888,7 +2007,7 @@ static int stop (mddev_t *mddev)
1888 shrink_stripes(conf); 2007 shrink_stripes(conf);
1889 free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); 2008 free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER);
1890 blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ 2009 blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
1891 kfree(conf); 2010 kobject_unregister(&conf->kobj);
1892 mddev->private = NULL; 2011 mddev->private = NULL;
1893 return 0; 2012 return 0;
1894} 2013}
diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
index f025ba6fb14c..5f4e945c8083 100644
--- a/include/linux/raid/raid5.h
+++ b/include/linux/raid/raid5.h
@@ -228,6 +228,7 @@ struct raid5_private_data {
228 * Cleared when a sync completes. 228 * Cleared when a sync completes.
229 */ 229 */
230 230
231 struct kobject kobj;
231 /* 232 /*
232 * Free stripes pool 233 * Free stripes pool
233 */ 234 */