aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/raid5-ppl.c6
-rw-r--r--drivers/md/raid5.c87
-rw-r--r--drivers/md/raid5.h9
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 */
1397static addr_conv_t *to_addr_conv(struct stripe_head *sh, 1396static 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 */
1407static struct page **to_addr_page(struct raid5_percpu *percpu, int i) 1402static 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
1415static struct dma_async_tx_descriptor * 1408static 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 */
2241static struct flex_array *scribble_alloc(int num, int cnt, gfp_t flags) 2234static 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
2258static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors) 2253static 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)
6742static void free_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu) 6732static 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
6751static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu) 6740static 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;