From: Shaohua Li <shli@kernel.org>
To: linux-raid@vger.kernel.org, neilb@suse.de
Subject: [patch 2/2]raid5: add a sysfs entry to change stripe size
Date: Tue, 8 Jul 2014 09:01:33 +0800 [thread overview]
Message-ID: <20140708010133.GB8941@kernel.org> (raw)
Add a sysfs entry to change stripe size.
Signed-off-by: Shaohua Li <shli@fusionio.com>
---
drivers/md/raid5.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 98 insertions(+), 11 deletions(-)
Index: linux/drivers/md/raid5.c
===================================================================
--- linux.orig/drivers/md/raid5.c 2014-07-08 08:48:02.788106833 +0800
+++ linux/drivers/md/raid5.c 2014-07-08 08:48:02.780106934 +0800
@@ -1906,10 +1906,10 @@ static void init_stripe_pointer(struct r
}
}
-static int grow_one_stripe(struct r5conf *conf, int hash)
+static int grow_one_stripe(struct r5conf *conf, int hash, gfp_t gfp)
{
struct stripe_head *sh;
- sh = kmem_cache_zalloc(conf->slab_cache, GFP_KERNEL);
+ sh = kmem_cache_zalloc(conf->slab_cache, gfp);
if (!sh)
return 0;
@@ -1932,7 +1932,7 @@ static int grow_one_stripe(struct r5conf
return 1;
}
-static int grow_stripes(struct r5conf *conf, int num)
+static int grow_stripes(struct r5conf *conf, int num, gfp_t gfp)
{
struct kmem_cache *sc;
int devs = max(conf->raid_disks, conf->previous_raid_disks);
@@ -1956,7 +1956,7 @@ static int grow_stripes(struct r5conf *c
conf->pool_size = devs;
hash = conf->max_nr_stripes % NR_STRIPE_HASH_LOCKS;
while (num--) {
- if (!grow_one_stripe(conf, hash))
+ if (!grow_one_stripe(conf, hash, gfp))
return 1;
conf->max_nr_stripes++;
hash = (hash + 1) % NR_STRIPE_HASH_LOCKS;
@@ -5537,7 +5537,7 @@ raid5_set_cache_size(struct mddev *mddev
return err;
hash = conf->max_nr_stripes % NR_STRIPE_HASH_LOCKS;
while (size > conf->max_nr_stripes) {
- if (grow_one_stripe(conf, hash))
+ if (grow_one_stripe(conf, hash, GFP_KERNEL))
conf->max_nr_stripes++;
else break;
hash = (hash + 1) % NR_STRIPE_HASH_LOCKS;
@@ -5729,12 +5729,97 @@ raid5_group_thread_cnt = __ATTR(group_th
raid5_show_group_thread_cnt,
raid5_store_group_thread_cnt);
+static ssize_t
+raid5_show_stripe_size(struct mddev *mddev, char *page)
+{
+ struct r5conf *conf = mddev->private;
+ if (conf)
+ return sprintf(page, "%ld\n", PAGE_SIZE << conf->stripe_size_order);
+ else
+ return 0;
+}
+
+static void free_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu);
+static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu,
+ gfp_t gfp);
+static ssize_t
+raid5_store_stripe_size(struct mddev *mddev, const char *page, size_t len)
+{
+ struct r5conf *conf = mddev->private;
+ unsigned long new, chunk_size;
+ int err = 0;
+ int cpu;
+ int nr_stripes;
+
+ if (len >= PAGE_SIZE)
+ return -EINVAL;
+ if (!conf)
+ return -ENODEV;
+
+ if (kstrtoul(page, 10, &new))
+ return -EINVAL;
+
+ new = ilog2(new);
+ if (new == (PAGE_SIZE << conf->stripe_size_order))
+ return len;
+ chunk_size = conf->chunk_sectors * 512;
+ if ((1 << new) > chunk_size || (1 << new) < PAGE_SIZE)
+ return -EINVAL;
+ new -= PAGE_SHIFT;
+
+ mddev_suspend(mddev);
+
+ if (conf->worker_groups)
+ flush_workqueue(raid5_wq);
+
+ nr_stripes = conf->max_nr_stripes;
+ shrink_stripes(conf);
+ conf->max_nr_stripes = 0;
+
+ get_online_cpus();
+ for_each_possible_cpu(cpu) {
+ struct raid5_percpu *percpu;
+
+ percpu = per_cpu_ptr(conf->percpu, cpu);
+ free_scratch_buffer(conf, percpu);
+ }
+
+ conf->stripe_size_order = new;
+
+ conf->scribble_len = scribble_len(conf, conf->pool_size);
+ for_each_present_cpu(cpu) {
+ struct raid5_percpu *percpu;
+
+ percpu = per_cpu_ptr(conf->percpu, cpu);
+ err = alloc_scratch_buffer(conf, percpu, GFP_NOIO);
+ if (err)
+ break;
+ }
+
+ put_online_cpus();
+
+ if (!err)
+ err = grow_stripes(conf, nr_stripes, GFP_NOIO);
+
+ mddev_resume(mddev);
+
+ if (err)
+ return err;
+ return len;
+}
+static struct md_sysfs_entry
+raid5_stripe_size = __ATTR(stripe_size, S_IRUGO | S_IWUSR,
+ raid5_show_stripe_size,
+ raid5_store_stripe_size);
+
+
static struct attribute *raid5_attrs[] = {
&raid5_stripecache_size.attr,
&raid5_stripecache_active.attr,
&raid5_preread_bypass_threshold.attr,
&raid5_group_thread_cnt.attr,
&raid5_skip_copy.attr,
+ &raid5_stripe_size.attr,
NULL,
};
static struct attribute_group raid5_attrs_group = {
@@ -5822,12 +5907,13 @@ static void free_scratch_buffer(struct r
percpu->scribble = NULL;
}
-static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu)
+static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu,
+ gfp_t gfp)
{
if (conf->level == 6 && !percpu->spare_page)
- percpu->spare_page = alloc_pages(GFP_KERNEL, conf->stripe_size_order);
+ percpu->spare_page = alloc_pages(gfp, conf->stripe_size_order);
if (!percpu->scribble)
- percpu->scribble = kmalloc(conf->scribble_len, GFP_KERNEL);
+ percpu->scribble = kmalloc(conf->scribble_len, gfp);
if (!percpu->scribble || (conf->level == 6 && !percpu->spare_page)) {
free_scratch_buffer(conf, percpu);
@@ -5877,7 +5963,7 @@ static int raid456_cpu_notify(struct not
switch (action) {
case CPU_UP_PREPARE:
case CPU_UP_PREPARE_FROZEN:
- if (alloc_scratch_buffer(conf, percpu)) {
+ if (alloc_scratch_buffer(conf, percpu, GFP_KERNEL)) {
pr_err("%s: failed memory allocation for cpu%ld\n",
__func__, cpu);
return notifier_from_errno(-ENOMEM);
@@ -5913,7 +5999,8 @@ static int raid5_alloc_percpu(struct r5c
get_online_cpus();
for_each_present_cpu(cpu) {
- err = alloc_scratch_buffer(conf, per_cpu_ptr(conf->percpu, cpu));
+ err = alloc_scratch_buffer(conf, per_cpu_ptr(conf->percpu, cpu),
+ GFP_KERNEL);
if (err) {
pr_err("%s: failed memory allocation for cpu%ld\n",
__func__, cpu);
@@ -6073,7 +6160,7 @@ static struct r5conf *setup_conf(struct
memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
max_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024;
atomic_set(&conf->empty_inactive_list_nr, NR_STRIPE_HASH_LOCKS);
- if (grow_stripes(conf, NR_STRIPES)) {
+ if (grow_stripes(conf, NR_STRIPES, GFP_KERNEL)) {
printk(KERN_ERR
"md/raid:%s: couldn't allocate %dkB for buffers\n",
mdname(mddev), memory);
reply other threads:[~2014-07-08 1:01 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140708010133.GB8941@kernel.org \
--to=shli@kernel.org \
--cc=linux-raid@vger.kernel.org \
--cc=neilb@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.