Skip to content

Commit 3f294f4

Browse files
neilbrownLinus Torvalds
authored andcommitted
[PATCH] md: add kobject/sysfs support to raid5
/sys/block/mdX/md/raid5/ contains raid5-related attributes. Currently stripe_cache_size is number of entries in stripe cache, and is settable. stripe_cache_active is number of active entries, and in only readable. Signed-off-by: Neil Brown <neilb@suse.de> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
1 parent 86e6ffd commit 3f294f4

File tree

2 files changed

+152
-32
lines changed

2 files changed

+152
-32
lines changed

drivers/md/raid5.c

Lines changed: 151 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,31 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
293293
return sh;
294294
}
295295

296-
static int grow_stripes(raid5_conf_t *conf, int num)
296+
static int grow_one_stripe(raid5_conf_t *conf)
297297
{
298298
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+
319+
static int grow_stripes(raid5_conf_t *conf, int num)
320+
{
299321
kmem_cache_t *sc;
300322
int devs = conf->raid_disks;
301323

@@ -308,43 +330,34 @@ static int grow_stripes(raid5_conf_t *conf, int num)
308330
return 1;
309331
conf->slab_cache = sc;
310332
while (num--) {
311-
sh = kmem_cache_alloc(sc, GFP_KERNEL);
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);
333+
if (!grow_one_stripe(conf))
321334
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);
328335
}
329336
return 0;
330337
}
331338

332-
static void shrink_stripes(raid5_conf_t *conf)
339+
static int drop_one_stripe(raid5_conf_t *conf)
333340
{
334341
struct stripe_head *sh;
335342

336-
while (1) {
337-
spin_lock_irq(&conf->device_lock);
338-
sh = get_free_stripe(conf);
339-
spin_unlock_irq(&conf->device_lock);
340-
if (!sh)
341-
break;
342-
if (atomic_read(&sh->count))
343-
BUG();
344-
shrink_buffers(sh, conf->raid_disks);
345-
kmem_cache_free(conf->slab_cache, sh);
346-
atomic_dec(&conf->active_stripes);
347-
}
343+
spin_lock_irq(&conf->device_lock);
344+
sh = get_free_stripe(conf);
345+
spin_unlock_irq(&conf->device_lock);
346+
if (!sh)
347+
return 0;
348+
if (atomic_read(&sh->count))
349+
BUG();
350+
shrink_buffers(sh, conf->raid_disks);
351+
kmem_cache_free(conf->slab_cache, sh);
352+
atomic_dec(&conf->active_stripes);
353+
return 1;
354+
}
355+
356+
static void shrink_stripes(raid5_conf_t *conf)
357+
{
358+
while (drop_one_stripe(conf))
359+
;
360+
348361
kmem_cache_destroy(conf->slab_cache);
349362
conf->slab_cache = NULL;
350363
}
@@ -1714,6 +1727,108 @@ static void raid5d (mddev_t *mddev)
17141727
PRINTK("--- raid5d inactive\n");
17151728
}
17161729

1730+
struct 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+
1736+
static ssize_t
1737+
raid5_show_stripe_cache_size(raid5_conf_t *conf, char *page)
1738+
{
1739+
return sprintf(page, "%d\n", conf->max_nr_stripes);
1740+
}
1741+
1742+
static ssize_t
1743+
raid5_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+
}
1768+
static 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+
1774+
static ssize_t
1775+
raid5_show_stripe_cache_active(raid5_conf_t *conf, char *page)
1776+
{
1777+
return sprintf(page, "%d\n", atomic_read(&conf->active_stripes));
1778+
}
1779+
1780+
static 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+
1785+
static struct attribute *raid5_default_attrs[] = {
1786+
&raid5_stripecache_size.attr,
1787+
&raid5_stripecache_active.attr,
1788+
NULL,
1789+
};
1790+
1791+
static ssize_t
1792+
raid5_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+
1802+
static ssize_t
1803+
raid5_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+
1814+
static 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+
1821+
static struct sysfs_ops raid5_sysfs_ops = {
1822+
.show = raid5_attr_show,
1823+
.store = raid5_attr_store,
1824+
};
1825+
1826+
static struct kobj_type raid5_ktype = {
1827+
.release = raid5_free,
1828+
.sysfs_ops = &raid5_sysfs_ops,
1829+
.default_attrs = raid5_default_attrs,
1830+
};
1831+
17171832
static int run(mddev_t *mddev)
17181833
{
17191834
raid5_conf_t *conf;
@@ -1855,6 +1970,10 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
18551970
}
18561971

18571972
/* 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);
18581977

18591978
if (mddev->bitmap)
18601979
mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
@@ -1879,7 +1998,7 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
18791998

18801999

18812000

1882-
static int stop (mddev_t *mddev)
2001+
static int stop(mddev_t *mddev)
18832002
{
18842003
raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
18852004

@@ -1888,7 +2007,7 @@ static int stop (mddev_t *mddev)
18882007
shrink_stripes(conf);
18892008
free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER);
18902009
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
1891-
kfree(conf);
2010+
kobject_unregister(&conf->kobj);
18922011
mddev->private = NULL;
18932012
return 0;
18942013
}

include/linux/raid/raid5.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ struct raid5_private_data {
228228
* Cleared when a sync completes.
229229
*/
230230

231+
struct kobject kobj;
231232
/*
232233
* Free stripes pool
233234
*/

0 commit comments

Comments
 (0)