Loading drivers/md/raid6main.c +115 −34 Original line number Diff line number Diff line Loading @@ -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); } } Loading Loading @@ -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); Loading Loading @@ -302,58 +303,69 @@ 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; 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--) { sh = kmem_cache_alloc(sc, GFP_KERNEL); sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL); if (!sh) return 1; memset(sh, 0, sizeof(*sh) + (devs-1)*sizeof(struct r5dev)); 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(sc, sh); return 1; 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; 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; } static void shrink_stripes(raid6_conf_t *conf) static int drop_one_stripe(raid6_conf_t *conf) { struct stripe_head *sh; while (1) { spin_lock_irq(&conf->device_lock); sh = get_free_stripe(conf); spin_unlock_irq(&conf->device_lock); if (!sh) break; 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)) ; kmem_cache_destroy(conf->slab_cache); conf->slab_cache = NULL; } Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading
drivers/md/raid6main.c +115 −34 Original line number Diff line number Diff line Loading @@ -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); } } Loading Loading @@ -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); Loading Loading @@ -302,58 +303,69 @@ 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; 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--) { sh = kmem_cache_alloc(sc, GFP_KERNEL); sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL); if (!sh) return 1; memset(sh, 0, sizeof(*sh) + (devs-1)*sizeof(struct r5dev)); 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(sc, sh); return 1; 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; 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; } static void shrink_stripes(raid6_conf_t *conf) static int drop_one_stripe(raid6_conf_t *conf) { struct stripe_head *sh; while (1) { spin_lock_irq(&conf->device_lock); sh = get_free_stripe(conf); spin_unlock_irq(&conf->device_lock); if (!sh) break; 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)) ; kmem_cache_destroy(conf->slab_cache); conf->slab_cache = NULL; } Loading Loading @@ -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; Loading Loading @@ -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; Loading