[PATCH] md: Add sysfs access to raid6 stripe cache size
authorNeilBrown <neilb@suse.de>
Thu, 2 Feb 2006 22:28:06 +0000 (14:28 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 2 Feb 2006 23:07:12 +0000 (15:07 -0800)
.. just as we already have for raid5.

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>
drivers/md/raid6main.c

index f618a53b98bee235cca1160e4d08b16bd955ff0c..ed2abb2e2e2d43a5f22b2a5b51c3ebdd093cbf69 100644 (file)
@@ -115,7 +115,7 @@ static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
                        list_add_tail(&sh->lru, &conf->inactive_list);
                        atomic_dec(&conf->active_stripes);
                        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);
                }
        }
@@ -273,7 +273,8 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector
                                conf->inactive_blocked = 1;
                                wait_event_lock_irq(conf->wait_for_stripe,
                                                    !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->device_lock,
                                                    unplug_slaves(conf->mddev);
@@ -302,9 +303,31 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector
        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;
+       sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
+       if (!sh)
+               return 0;
+       memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
+       sh->raid_conf = conf;
+       spin_lock_init(&sh->lock);
+
+       if (grow_buffers(sh, conf->raid_disks)) {
+               shrink_buffers(sh, conf->raid_disks);
+               kmem_cache_free(conf->slab_cache, sh);
+               return 0;
+       }
+       /* we just created an active stripe so... */
+       atomic_set(&sh->count, 1);
+       atomic_inc(&conf->active_stripes);
+       INIT_LIST_HEAD(&sh->lru);
+       release_stripe(sh);
+       return 1;
+}
+
+static int grow_stripes(raid6_conf_t *conf, int num)
+{
        kmem_cache_t *sc;
        int devs = conf->raid_disks;
 
@@ -316,44 +339,33 @@ static int grow_stripes(raid6_conf_t *conf, int num)
        if (!sc)
                return 1;
        conf->slab_cache = sc;
-       while (num--) {
-               sh = kmem_cache_alloc(sc, GFP_KERNEL);
-               if (!sh)
-                       return 1;
-               memset(sh, 0, sizeof(*sh) + (devs-1)*sizeof(struct r5dev));
-               sh->raid_conf = conf;
-               spin_lock_init(&sh->lock);
-
-               if (grow_buffers(sh, conf->raid_disks)) {
-                       shrink_buffers(sh, conf->raid_disks);
-                       kmem_cache_free(sc, sh);
+       while (num--)
+               if (!grow_one_stripe(conf))
                        return 1;
-               }
-               /* we just created an active stripe so... */
-               atomic_set(&sh->count, 1);
-               atomic_inc(&conf->active_stripes);
-               INIT_LIST_HEAD(&sh->lru);
-               release_stripe(sh);
-       }
        return 0;
 }
 
-static void shrink_stripes(raid6_conf_t *conf)
+static int drop_one_stripe(raid6_conf_t *conf)
 {
        struct stripe_head *sh;
+       spin_lock_irq(&conf->device_lock);
+       sh = get_free_stripe(conf);
+       spin_unlock_irq(&conf->device_lock);
+       if (!sh)
+               return 0;
+       if (atomic_read(&sh->count))
+               BUG();
+       shrink_buffers(sh, conf->raid_disks);
+       kmem_cache_free(conf->slab_cache, sh);
+       atomic_dec(&conf->active_stripes);
+       return 1;
+}
+
+static void shrink_stripes(raid6_conf_t *conf)
+{
+       while (drop_one_stripe(conf))
+               ;
 
-       while (1) {
-               spin_lock_irq(&conf->device_lock);
-               sh = get_free_stripe(conf);
-               spin_unlock_irq(&conf->device_lock);
-               if (!sh)
-                       break;
-               if (atomic_read(&sh->count))
-                       BUG();
-               shrink_buffers(sh, conf->raid_disks);
-               kmem_cache_free(conf->slab_cache, sh);
-               atomic_dec(&conf->active_stripes);
-       }
        kmem_cache_destroy(conf->slab_cache);
        conf->slab_cache = NULL;
 }
@@ -1912,6 +1924,74 @@ static void raid6d (mddev_t *mddev)
        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)
 {
        raid6_conf_t *conf;
@@ -2095,6 +2175,7 @@ static int stop (mddev_t *mddev)
        shrink_stripes(conf);
        kfree(conf->stripe_hashtbl);
        blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
+       sysfs_remove_group(&mddev->kobj, &raid6_attrs_group);
        kfree(conf);
        mddev->private = NULL;
        return 0;