Commit 35849c75 authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds

[PATCH] md: Add sysfs access to raid6 stripe cache size

.. just as we already have for raid5.
Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 978f946b
...@@ -115,7 +115,7 @@ static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) ...@@ -115,7 +115,7 @@ static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
list_add_tail(&sh->lru, &conf->inactive_list); list_add_tail(&sh->lru, &conf->inactive_list);
atomic_dec(&conf->active_stripes); atomic_dec(&conf->active_stripes);
if (!conf->inactive_blocked || if (!conf->inactive_blocked ||
atomic_read(&conf->active_stripes) < (NR_STRIPES*3/4)) atomic_read(&conf->active_stripes) < (conf->max_nr_stripes*3/4))
wake_up(&conf->wait_for_stripe); wake_up(&conf->wait_for_stripe);
} }
} }
...@@ -273,7 +273,8 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector ...@@ -273,7 +273,8 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector
conf->inactive_blocked = 1; conf->inactive_blocked = 1;
wait_event_lock_irq(conf->wait_for_stripe, wait_event_lock_irq(conf->wait_for_stripe,
!list_empty(&conf->inactive_list) && !list_empty(&conf->inactive_list) &&
(atomic_read(&conf->active_stripes) < (NR_STRIPES *3/4) (atomic_read(&conf->active_stripes)
< (conf->max_nr_stripes *3/4)
|| !conf->inactive_blocked), || !conf->inactive_blocked),
conf->device_lock, conf->device_lock,
unplug_slaves(conf->mddev); unplug_slaves(conf->mddev);
...@@ -302,58 +303,69 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector ...@@ -302,58 +303,69 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector
return sh; return sh;
} }
static int grow_stripes(raid6_conf_t *conf, int num) static int grow_one_stripe(raid6_conf_t *conf)
{ {
struct stripe_head *sh; struct stripe_head *sh;
kmem_cache_t *sc; sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
int devs = conf->raid_disks;
sprintf(conf->cache_name, "raid6/%s", mdname(conf->mddev));
sc = kmem_cache_create(conf->cache_name,
sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
0, 0, NULL, NULL);
if (!sc)
return 1;
conf->slab_cache = sc;
while (num--) {
sh = kmem_cache_alloc(sc, GFP_KERNEL);
if (!sh) if (!sh)
return 1; return 0;
memset(sh, 0, sizeof(*sh) + (devs-1)*sizeof(struct r5dev)); memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
sh->raid_conf = conf; sh->raid_conf = conf;
spin_lock_init(&sh->lock); spin_lock_init(&sh->lock);
if (grow_buffers(sh, conf->raid_disks)) { if (grow_buffers(sh, conf->raid_disks)) {
shrink_buffers(sh, conf->raid_disks); shrink_buffers(sh, conf->raid_disks);
kmem_cache_free(sc, sh); kmem_cache_free(conf->slab_cache, sh);
return 1; return 0;
} }
/* we just created an active stripe so... */ /* we just created an active stripe so... */
atomic_set(&sh->count, 1); atomic_set(&sh->count, 1);
atomic_inc(&conf->active_stripes); atomic_inc(&conf->active_stripes);
INIT_LIST_HEAD(&sh->lru); INIT_LIST_HEAD(&sh->lru);
release_stripe(sh); release_stripe(sh);
} return 1;
}
static int grow_stripes(raid6_conf_t *conf, int num)
{
kmem_cache_t *sc;
int devs = conf->raid_disks;
sprintf(conf->cache_name, "raid6/%s", mdname(conf->mddev));
sc = kmem_cache_create(conf->cache_name,
sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
0, 0, NULL, NULL);
if (!sc)
return 1;
conf->slab_cache = sc;
while (num--)
if (!grow_one_stripe(conf))
return 1;
return 0; return 0;
} }
static void shrink_stripes(raid6_conf_t *conf) static int drop_one_stripe(raid6_conf_t *conf)
{ {
struct stripe_head *sh; struct stripe_head *sh;
while (1) {
spin_lock_irq(&conf->device_lock); spin_lock_irq(&conf->device_lock);
sh = get_free_stripe(conf); sh = get_free_stripe(conf);
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
if (!sh) if (!sh)
break; return 0;
if (atomic_read(&sh->count)) if (atomic_read(&sh->count))
BUG(); BUG();
shrink_buffers(sh, conf->raid_disks); shrink_buffers(sh, conf->raid_disks);
kmem_cache_free(conf->slab_cache, sh); kmem_cache_free(conf->slab_cache, sh);
atomic_dec(&conf->active_stripes); atomic_dec(&conf->active_stripes);
} return 1;
}
static void shrink_stripes(raid6_conf_t *conf)
{
while (drop_one_stripe(conf))
;
kmem_cache_destroy(conf->slab_cache); kmem_cache_destroy(conf->slab_cache);
conf->slab_cache = NULL; conf->slab_cache = NULL;
} }
...@@ -1912,6 +1924,74 @@ static void raid6d (mddev_t *mddev) ...@@ -1912,6 +1924,74 @@ static void raid6d (mddev_t *mddev)
PRINTK("--- raid6d inactive\n"); PRINTK("--- raid6d inactive\n");
} }
static ssize_t
raid6_show_stripe_cache_size(mddev_t *mddev, char *page)
{
raid6_conf_t *conf = mddev_to_conf(mddev);
if (conf)
return sprintf(page, "%d\n", conf->max_nr_stripes);
else
return 0;
}
static ssize_t
raid6_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
{
raid6_conf_t *conf = mddev_to_conf(mddev);
char *end;
int new;
if (len >= PAGE_SIZE)
return -EINVAL;
if (!conf)
return -ENODEV;
new = simple_strtoul(page, &end, 10);
if (!*page || (*end && *end != '\n') )
return -EINVAL;
if (new <= 16 || new > 32768)
return -EINVAL;
while (new < conf->max_nr_stripes) {
if (drop_one_stripe(conf))
conf->max_nr_stripes--;
else
break;
}
while (new > conf->max_nr_stripes) {
if (grow_one_stripe(conf))
conf->max_nr_stripes++;
else break;
}
return len;
}
static struct md_sysfs_entry
raid6_stripecache_size = __ATTR(stripe_cache_size, S_IRUGO | S_IWUSR,
raid6_show_stripe_cache_size,
raid6_store_stripe_cache_size);
static ssize_t
stripe_cache_active_show(mddev_t *mddev, char *page)
{
raid6_conf_t *conf = mddev_to_conf(mddev);
if (conf)
return sprintf(page, "%d\n", atomic_read(&conf->active_stripes));
else
return 0;
}
static struct md_sysfs_entry
raid6_stripecache_active = __ATTR_RO(stripe_cache_active);
static struct attribute *raid6_attrs[] = {
&raid6_stripecache_size.attr,
&raid6_stripecache_active.attr,
NULL,
};
static struct attribute_group raid6_attrs_group = {
.name = NULL,
.attrs = raid6_attrs,
};
static int run(mddev_t *mddev) static int run(mddev_t *mddev)
{ {
raid6_conf_t *conf; raid6_conf_t *conf;
...@@ -2095,6 +2175,7 @@ static int stop (mddev_t *mddev) ...@@ -2095,6 +2175,7 @@ static int stop (mddev_t *mddev)
shrink_stripes(conf); shrink_stripes(conf);
kfree(conf->stripe_hashtbl); kfree(conf->stripe_hashtbl);
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
sysfs_remove_group(&mddev->kobj, &raid6_attrs_group);
kfree(conf); kfree(conf);
mddev->private = NULL; mddev->private = NULL;
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment