aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/raid5.c65
1 files changed, 43 insertions, 22 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 9748e525e4c0..3873eaa6fa2e 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2068,6 +2068,35 @@ static struct flex_array *scribble_alloc(int num, int cnt, gfp_t flags)
2068 return ret; 2068 return ret;
2069} 2069}
2070 2070
2071static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors)
2072{
2073 unsigned long cpu;
2074 int err = 0;
2075
2076 mddev_suspend(conf->mddev);
2077 get_online_cpus();
2078 for_each_present_cpu(cpu) {
2079 struct raid5_percpu *percpu;
2080 struct flex_array *scribble;
2081
2082 percpu = per_cpu_ptr(conf->percpu, cpu);
2083 scribble = scribble_alloc(new_disks,
2084 new_sectors / STRIPE_SECTORS,
2085 GFP_NOIO);
2086
2087 if (scribble) {
2088 flex_array_free(percpu->scribble);
2089 percpu->scribble = scribble;
2090 } else {
2091 err = -ENOMEM;
2092 break;
2093 }
2094 }
2095 put_online_cpus();
2096 mddev_resume(conf->mddev);
2097 return err;
2098}
2099
2071static int resize_stripes(struct r5conf *conf, int newsize) 2100static int resize_stripes(struct r5conf *conf, int newsize)
2072{ 2101{
2073 /* Make all the stripes able to hold 'newsize' devices. 2102 /* Make all the stripes able to hold 'newsize' devices.
@@ -2096,7 +2125,6 @@ static int resize_stripes(struct r5conf *conf, int newsize)
2096 struct stripe_head *osh, *nsh; 2125 struct stripe_head *osh, *nsh;
2097 LIST_HEAD(newstripes); 2126 LIST_HEAD(newstripes);
2098 struct disk_info *ndisks; 2127 struct disk_info *ndisks;
2099 unsigned long cpu;
2100 int err; 2128 int err;
2101 struct kmem_cache *sc; 2129 struct kmem_cache *sc;
2102 int i; 2130 int i;
@@ -2178,25 +2206,6 @@ static int resize_stripes(struct r5conf *conf, int newsize)
2178 } else 2206 } else
2179 err = -ENOMEM; 2207 err = -ENOMEM;
2180 2208
2181 get_online_cpus();
2182 for_each_present_cpu(cpu) {
2183 struct raid5_percpu *percpu;
2184 struct flex_array *scribble;
2185
2186 percpu = per_cpu_ptr(conf->percpu, cpu);
2187 scribble = scribble_alloc(newsize, conf->chunk_sectors /
2188 STRIPE_SECTORS, GFP_NOIO);
2189
2190 if (scribble) {
2191 flex_array_free(percpu->scribble);
2192 percpu->scribble = scribble;
2193 } else {
2194 err = -ENOMEM;
2195 break;
2196 }
2197 }
2198 put_online_cpus();
2199
2200 /* Step 4, return new stripes to service */ 2209 /* Step 4, return new stripes to service */
2201 while(!list_empty(&newstripes)) { 2210 while(!list_empty(&newstripes)) {
2202 nsh = list_entry(newstripes.next, struct stripe_head, lru); 2211 nsh = list_entry(newstripes.next, struct stripe_head, lru);
@@ -6228,8 +6237,11 @@ static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu
6228 percpu->spare_page = alloc_page(GFP_KERNEL); 6237 percpu->spare_page = alloc_page(GFP_KERNEL);
6229 if (!percpu->scribble) 6238 if (!percpu->scribble)
6230 percpu->scribble = scribble_alloc(max(conf->raid_disks, 6239 percpu->scribble = scribble_alloc(max(conf->raid_disks,
6231 conf->previous_raid_disks), conf->chunk_sectors / 6240 conf->previous_raid_disks),
6232 STRIPE_SECTORS, GFP_KERNEL); 6241 max(conf->chunk_sectors,
6242 conf->prev_chunk_sectors)
6243 / STRIPE_SECTORS,
6244 GFP_KERNEL);
6233 6245
6234 if (!percpu->scribble || (conf->level == 6 && !percpu->spare_page)) { 6246 if (!percpu->scribble || (conf->level == 6 && !percpu->spare_page)) {
6235 free_scratch_buffer(conf, percpu); 6247 free_scratch_buffer(conf, percpu);
@@ -7205,6 +7217,15 @@ static int check_reshape(struct mddev *mddev)
7205 if (!check_stripe_cache(mddev)) 7217 if (!check_stripe_cache(mddev))
7206 return -ENOSPC; 7218 return -ENOSPC;
7207 7219
7220 if (mddev->new_chunk_sectors > mddev->chunk_sectors ||
7221 mddev->delta_disks > 0)
7222 if (resize_chunks(conf,
7223 conf->previous_raid_disks
7224 + max(0, mddev->delta_disks),
7225 max(mddev->new_chunk_sectors,
7226 mddev->chunk_sectors)
7227 ) < 0)
7228 return -ENOMEM;
7208 return resize_stripes(conf, (conf->previous_raid_disks 7229 return resize_stripes(conf, (conf->previous_raid_disks
7209 + mddev->delta_disks)); 7230 + mddev->delta_disks));
7210} 7231}