raid5: sysfs entry to control worker thread number
authorShaohua Li <shli@kernel.org>
Tue, 27 Aug 2013 09:50:42 +0000 (17:50 +0800)
committerNeilBrown <neilb@suse.de>
Wed, 28 Aug 2013 06:56:52 +0000 (16:56 +1000)
Add a sysfs entry to control running workqueue thread number. If
group_thread_cnt is set to 0, we will disable workqueue offload handling of
stripes.

Signed-off-by: Shaohua Li <shli@fusionio.com>
Signed-off-by: NeilBrown <neilb@suse.de>
drivers/md/raid5.c

index 32fa1131cafcf7dccf768481541181cbbc1ad918..d79ecd9032694a85bebcfe7e354c1b1bff146614 100644 (file)
@@ -5145,10 +5145,70 @@ stripe_cache_active_show(struct mddev *mddev, char *page)
 static struct md_sysfs_entry
 raid5_stripecache_active = __ATTR_RO(stripe_cache_active);
 
+static ssize_t
+raid5_show_group_thread_cnt(struct mddev *mddev, char *page)
+{
+       struct r5conf *conf = mddev->private;
+       if (conf)
+               return sprintf(page, "%d\n", conf->worker_cnt_per_group);
+       else
+               return 0;
+}
+
+static int alloc_thread_groups(struct r5conf *conf, int cnt);
+static ssize_t
+raid5_store_group_thread_cnt(struct mddev *mddev, const char *page, size_t len)
+{
+       struct r5conf *conf = mddev->private;
+       unsigned long new;
+       int err;
+       struct r5worker_group *old_groups;
+       int old_group_cnt;
+
+       if (len >= PAGE_SIZE)
+               return -EINVAL;
+       if (!conf)
+               return -ENODEV;
+
+       if (kstrtoul(page, 10, &new))
+               return -EINVAL;
+
+       if (new == conf->worker_cnt_per_group)
+               return len;
+
+       mddev_suspend(mddev);
+
+       old_groups = conf->worker_groups;
+       old_group_cnt = conf->worker_cnt_per_group;
+
+       conf->worker_groups = NULL;
+       err = alloc_thread_groups(conf, new);
+       if (err) {
+               conf->worker_groups = old_groups;
+               conf->worker_cnt_per_group = old_group_cnt;
+       } else {
+               if (old_groups)
+                       kfree(old_groups[0].workers);
+               kfree(old_groups);
+       }
+
+       mddev_resume(mddev);
+
+       if (err)
+               return err;
+       return len;
+}
+
+static struct md_sysfs_entry
+raid5_group_thread_cnt = __ATTR(group_thread_cnt, S_IRUGO | S_IWUSR,
+                               raid5_show_group_thread_cnt,
+                               raid5_store_group_thread_cnt);
+
 static struct attribute *raid5_attrs[] =  {
        &raid5_stripecache_size.attr,
        &raid5_stripecache_active.attr,
        &raid5_preread_bypass_threshold.attr,
+       &raid5_group_thread_cnt.attr,
        NULL,
 };
 static struct attribute_group raid5_attrs_group = {