Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+115 −34
Original line number Original line Diff line number Diff line
@@ -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
				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
	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)
	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)
	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;