diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/md/raid5-ppl.c | 6 | ||||
| -rw-r--r-- | drivers/md/raid5.c | 87 | ||||
| -rw-r--r-- | drivers/md/raid5.h | 9 |
3 files changed, 46 insertions, 56 deletions
diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c index 3a7c36326589..0b096ddc9c1e 100644 --- a/drivers/md/raid5-ppl.c +++ b/drivers/md/raid5-ppl.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <linux/blkdev.h> | 16 | #include <linux/blkdev.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/crc32c.h> | 18 | #include <linux/crc32c.h> |
| 19 | #include <linux/flex_array.h> | ||
| 20 | #include <linux/async_tx.h> | 19 | #include <linux/async_tx.h> |
| 21 | #include <linux/raid/md_p.h> | 20 | #include <linux/raid/md_p.h> |
| 22 | #include "md.h" | 21 | #include "md.h" |
| @@ -165,7 +164,7 @@ ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu, | |||
| 165 | struct dma_async_tx_descriptor *tx) | 164 | struct dma_async_tx_descriptor *tx) |
| 166 | { | 165 | { |
| 167 | int disks = sh->disks; | 166 | int disks = sh->disks; |
| 168 | struct page **srcs = flex_array_get(percpu->scribble, 0); | 167 | struct page **srcs = percpu->scribble; |
| 169 | int count = 0, pd_idx = sh->pd_idx, i; | 168 | int count = 0, pd_idx = sh->pd_idx, i; |
| 170 | struct async_submit_ctl submit; | 169 | struct async_submit_ctl submit; |
| 171 | 170 | ||
| @@ -196,8 +195,7 @@ ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu, | |||
| 196 | } | 195 | } |
| 197 | 196 | ||
| 198 | init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST, tx, | 197 | init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST, tx, |
| 199 | NULL, sh, flex_array_get(percpu->scribble, 0) | 198 | NULL, sh, (void *) (srcs + sh->disks + 2)); |
| 200 | + sizeof(struct page *) * (sh->disks + 2)); | ||
| 201 | 199 | ||
| 202 | if (count == 1) | 200 | if (count == 1) |
| 203 | tx = async_memcpy(sh->ppl_page, srcs[0], 0, 0, PAGE_SIZE, | 201 | tx = async_memcpy(sh->ppl_page, srcs[0], 0, 0, PAGE_SIZE, |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index cecea901ab8c..77ffd09be486 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -54,7 +54,6 @@ | |||
| 54 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
| 55 | #include <linux/ratelimit.h> | 55 | #include <linux/ratelimit.h> |
| 56 | #include <linux/nodemask.h> | 56 | #include <linux/nodemask.h> |
| 57 | #include <linux/flex_array.h> | ||
| 58 | 57 | ||
| 59 | #include <trace/events/block.h> | 58 | #include <trace/events/block.h> |
| 60 | #include <linux/list_sort.h> | 59 | #include <linux/list_sort.h> |
| @@ -1394,22 +1393,16 @@ static void ops_complete_compute(void *stripe_head_ref) | |||
| 1394 | } | 1393 | } |
| 1395 | 1394 | ||
| 1396 | /* return a pointer to the address conversion region of the scribble buffer */ | 1395 | /* return a pointer to the address conversion region of the scribble buffer */ |
| 1397 | static addr_conv_t *to_addr_conv(struct stripe_head *sh, | 1396 | static struct page **to_addr_page(struct raid5_percpu *percpu, int i) |
| 1398 | struct raid5_percpu *percpu, int i) | ||
| 1399 | { | 1397 | { |
| 1400 | void *addr; | 1398 | return percpu->scribble + i * percpu->scribble_obj_size; |
| 1401 | |||
| 1402 | addr = flex_array_get(percpu->scribble, i); | ||
| 1403 | return addr + sizeof(struct page *) * (sh->disks + 2); | ||
| 1404 | } | 1399 | } |
| 1405 | 1400 | ||
| 1406 | /* return a pointer to the address conversion region of the scribble buffer */ | 1401 | /* return a pointer to the address conversion region of the scribble buffer */ |
| 1407 | static struct page **to_addr_page(struct raid5_percpu *percpu, int i) | 1402 | static addr_conv_t *to_addr_conv(struct stripe_head *sh, |
| 1403 | struct raid5_percpu *percpu, int i) | ||
| 1408 | { | 1404 | { |
| 1409 | void *addr; | 1405 | return (void *) (to_addr_page(percpu, i) + sh->disks + 2); |
| 1410 | |||
| 1411 | addr = flex_array_get(percpu->scribble, i); | ||
| 1412 | return addr; | ||
| 1413 | } | 1406 | } |
| 1414 | 1407 | ||
| 1415 | static struct dma_async_tx_descriptor * | 1408 | static struct dma_async_tx_descriptor * |
| @@ -2238,21 +2231,23 @@ static int grow_stripes(struct r5conf *conf, int num) | |||
| 2238 | * calculate over all devices (not just the data blocks), using zeros in place | 2231 | * calculate over all devices (not just the data blocks), using zeros in place |
| 2239 | * of the P and Q blocks. | 2232 | * of the P and Q blocks. |
| 2240 | */ | 2233 | */ |
| 2241 | static struct flex_array *scribble_alloc(int num, int cnt, gfp_t flags) | 2234 | static int scribble_alloc(struct raid5_percpu *percpu, |
| 2235 | int num, int cnt, gfp_t flags) | ||
| 2242 | { | 2236 | { |
| 2243 | struct flex_array *ret; | 2237 | size_t obj_size = |
| 2244 | size_t len; | 2238 | sizeof(struct page *) * (num+2) + |
| 2239 | sizeof(addr_conv_t) * (num+2); | ||
| 2240 | void *scribble; | ||
| 2245 | 2241 | ||
| 2246 | len = sizeof(struct page *) * (num+2) + sizeof(addr_conv_t) * (num+2); | 2242 | scribble = kvmalloc_array(cnt, obj_size, flags); |
| 2247 | ret = flex_array_alloc(len, cnt, flags); | 2243 | if (!scribble) |
| 2248 | if (!ret) | 2244 | return -ENOMEM; |
| 2249 | return NULL; | 2245 | |
| 2250 | /* always prealloc all elements, so no locking is required */ | 2246 | kvfree(percpu->scribble); |
| 2251 | if (flex_array_prealloc(ret, 0, cnt, flags)) { | 2247 | |
| 2252 | flex_array_free(ret); | 2248 | percpu->scribble = scribble; |
| 2253 | return NULL; | 2249 | percpu->scribble_obj_size = obj_size; |
| 2254 | } | 2250 | return 0; |
| 2255 | return ret; | ||
| 2256 | } | 2251 | } |
| 2257 | 2252 | ||
| 2258 | static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors) | 2253 | static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors) |
| @@ -2270,23 +2265,18 @@ static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors) | |||
| 2270 | return 0; | 2265 | return 0; |
| 2271 | mddev_suspend(conf->mddev); | 2266 | mddev_suspend(conf->mddev); |
| 2272 | get_online_cpus(); | 2267 | get_online_cpus(); |
| 2268 | |||
| 2273 | for_each_present_cpu(cpu) { | 2269 | for_each_present_cpu(cpu) { |
| 2274 | struct raid5_percpu *percpu; | 2270 | struct raid5_percpu *percpu; |
| 2275 | struct flex_array *scribble; | ||
| 2276 | 2271 | ||
| 2277 | percpu = per_cpu_ptr(conf->percpu, cpu); | 2272 | percpu = per_cpu_ptr(conf->percpu, cpu); |
| 2278 | scribble = scribble_alloc(new_disks, | 2273 | err = scribble_alloc(percpu, new_disks, |
| 2279 | new_sectors / STRIPE_SECTORS, | 2274 | new_sectors / STRIPE_SECTORS, |
| 2280 | GFP_NOIO); | 2275 | GFP_NOIO); |
| 2281 | 2276 | if (err) | |
| 2282 | if (scribble) { | ||
| 2283 | flex_array_free(percpu->scribble); | ||
| 2284 | percpu->scribble = scribble; | ||
| 2285 | } else { | ||
| 2286 | err = -ENOMEM; | ||
| 2287 | break; | 2277 | break; |
| 2288 | } | ||
| 2289 | } | 2278 | } |
| 2279 | |||
| 2290 | put_online_cpus(); | 2280 | put_online_cpus(); |
| 2291 | mddev_resume(conf->mddev); | 2281 | mddev_resume(conf->mddev); |
| 2292 | if (!err) { | 2282 | if (!err) { |
| @@ -6742,25 +6732,26 @@ raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks) | |||
| 6742 | static void free_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu) | 6732 | static void free_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu) |
| 6743 | { | 6733 | { |
| 6744 | safe_put_page(percpu->spare_page); | 6734 | safe_put_page(percpu->spare_page); |
| 6745 | if (percpu->scribble) | ||
| 6746 | flex_array_free(percpu->scribble); | ||
| 6747 | percpu->spare_page = NULL; | 6735 | percpu->spare_page = NULL; |
| 6736 | kvfree(percpu->scribble); | ||
| 6748 | percpu->scribble = NULL; | 6737 | percpu->scribble = NULL; |
| 6749 | } | 6738 | } |
| 6750 | 6739 | ||
| 6751 | static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu) | 6740 | static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu) |
| 6752 | { | 6741 | { |
| 6753 | if (conf->level == 6 && !percpu->spare_page) | 6742 | if (conf->level == 6 && !percpu->spare_page) { |
| 6754 | percpu->spare_page = alloc_page(GFP_KERNEL); | 6743 | percpu->spare_page = alloc_page(GFP_KERNEL); |
| 6755 | if (!percpu->scribble) | 6744 | if (!percpu->spare_page) |
| 6756 | percpu->scribble = scribble_alloc(max(conf->raid_disks, | 6745 | return -ENOMEM; |
| 6757 | conf->previous_raid_disks), | 6746 | } |
| 6758 | max(conf->chunk_sectors, | 6747 | |
| 6759 | conf->prev_chunk_sectors) | 6748 | if (scribble_alloc(percpu, |
| 6760 | / STRIPE_SECTORS, | 6749 | max(conf->raid_disks, |
| 6761 | GFP_KERNEL); | 6750 | conf->previous_raid_disks), |
| 6762 | 6751 | max(conf->chunk_sectors, | |
| 6763 | if (!percpu->scribble || (conf->level == 6 && !percpu->spare_page)) { | 6752 | conf->prev_chunk_sectors) |
| 6753 | / STRIPE_SECTORS, | ||
| 6754 | GFP_KERNEL)) { | ||
| 6764 | free_scratch_buffer(conf, percpu); | 6755 | free_scratch_buffer(conf, percpu); |
| 6765 | return -ENOMEM; | 6756 | return -ENOMEM; |
| 6766 | } | 6757 | } |
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index 8474c224127b..cf991f13403e 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h | |||
| @@ -638,10 +638,11 @@ struct r5conf { | |||
| 638 | /* per cpu variables */ | 638 | /* per cpu variables */ |
| 639 | struct raid5_percpu { | 639 | struct raid5_percpu { |
| 640 | struct page *spare_page; /* Used when checking P/Q in raid6 */ | 640 | struct page *spare_page; /* Used when checking P/Q in raid6 */ |
| 641 | struct flex_array *scribble; /* space for constructing buffer | 641 | void *scribble; /* space for constructing buffer |
| 642 | * lists and performing address | 642 | * lists and performing address |
| 643 | * conversions | 643 | * conversions |
| 644 | */ | 644 | */ |
| 645 | int scribble_obj_size; | ||
| 645 | } __percpu *percpu; | 646 | } __percpu *percpu; |
| 646 | int scribble_disks; | 647 | int scribble_disks; |
| 647 | int scribble_sectors; | 648 | int scribble_sectors; |
