md: convert to kvmalloc

The code really just wants a big flat buffer, so just do that.

Link: http://lkml.kernel.org/r/20181217131929.11727-3-kent.overstreet@gmail.com
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Reviewed-by: Matthew Wilcox <willy@infradead.org>
Cc: Shaohua Li <shli@kernel.org>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Eric Paris <eparis@parisplace.org>
Cc: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Paul Moore <paul@paul-moore.com>
Cc: Pravin B Shelar <pshelar@ovn.org>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Cc: Vlad Yasevich <vyasevich@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Kent Overstreet 2019-03-11 23:31:06 -07:00 committed by Linus Torvalds
parent ee9c5e6755
commit b330e6a49d
3 changed files with 45 additions and 55 deletions

View File

@ -16,7 +16,6 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/crc32c.h> #include <linux/crc32c.h>
#include <linux/flex_array.h>
#include <linux/async_tx.h> #include <linux/async_tx.h>
#include <linux/raid/md_p.h> #include <linux/raid/md_p.h>
#include "md.h" #include "md.h"
@ -165,7 +164,7 @@ ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu,
struct dma_async_tx_descriptor *tx) struct dma_async_tx_descriptor *tx)
{ {
int disks = sh->disks; int disks = sh->disks;
struct page **srcs = flex_array_get(percpu->scribble, 0); struct page **srcs = percpu->scribble;
int count = 0, pd_idx = sh->pd_idx, i; int count = 0, pd_idx = sh->pd_idx, i;
struct async_submit_ctl submit; struct async_submit_ctl submit;
@ -196,8 +195,7 @@ ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu,
} }
init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST, tx, init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST, tx,
NULL, sh, flex_array_get(percpu->scribble, 0) NULL, sh, (void *) (srcs + sh->disks + 2));
+ sizeof(struct page *) * (sh->disks + 2));
if (count == 1) if (count == 1)
tx = async_memcpy(sh->ppl_page, srcs[0], 0, 0, PAGE_SIZE, tx = async_memcpy(sh->ppl_page, srcs[0], 0, 0, PAGE_SIZE,

View File

@ -54,7 +54,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/nodemask.h> #include <linux/nodemask.h>
#include <linux/flex_array.h>
#include <trace/events/block.h> #include <trace/events/block.h>
#include <linux/list_sort.h> #include <linux/list_sort.h>
@ -1394,22 +1393,16 @@ static void ops_complete_compute(void *stripe_head_ref)
} }
/* return a pointer to the address conversion region of the scribble buffer */ /* return a pointer to the address conversion region of the scribble buffer */
static addr_conv_t *to_addr_conv(struct stripe_head *sh, static struct page **to_addr_page(struct raid5_percpu *percpu, int i)
struct raid5_percpu *percpu, int i)
{ {
void *addr; return percpu->scribble + i * percpu->scribble_obj_size;
addr = flex_array_get(percpu->scribble, i);
return addr + sizeof(struct page *) * (sh->disks + 2);
} }
/* return a pointer to the address conversion region of the scribble buffer */ /* return a pointer to the address conversion region of the scribble buffer */
static struct page **to_addr_page(struct raid5_percpu *percpu, int i) static addr_conv_t *to_addr_conv(struct stripe_head *sh,
struct raid5_percpu *percpu, int i)
{ {
void *addr; return (void *) (to_addr_page(percpu, i) + sh->disks + 2);
addr = flex_array_get(percpu->scribble, i);
return addr;
} }
static struct dma_async_tx_descriptor * static struct dma_async_tx_descriptor *
@ -2238,21 +2231,23 @@ static int grow_stripes(struct r5conf *conf, int num)
* calculate over all devices (not just the data blocks), using zeros in place * calculate over all devices (not just the data blocks), using zeros in place
* of the P and Q blocks. * of the P and Q blocks.
*/ */
static struct flex_array *scribble_alloc(int num, int cnt, gfp_t flags) static int scribble_alloc(struct raid5_percpu *percpu,
int num, int cnt, gfp_t flags)
{ {
struct flex_array *ret; size_t obj_size =
size_t len; sizeof(struct page *) * (num+2) +
sizeof(addr_conv_t) * (num+2);
void *scribble;
len = sizeof(struct page *) * (num+2) + sizeof(addr_conv_t) * (num+2); scribble = kvmalloc_array(cnt, obj_size, flags);
ret = flex_array_alloc(len, cnt, flags); if (!scribble)
if (!ret) return -ENOMEM;
return NULL;
/* always prealloc all elements, so no locking is required */ kvfree(percpu->scribble);
if (flex_array_prealloc(ret, 0, cnt, flags)) {
flex_array_free(ret); percpu->scribble = scribble;
return NULL; percpu->scribble_obj_size = obj_size;
} return 0;
return ret;
} }
static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors) 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)
return 0; return 0;
mddev_suspend(conf->mddev); mddev_suspend(conf->mddev);
get_online_cpus(); get_online_cpus();
for_each_present_cpu(cpu) { for_each_present_cpu(cpu) {
struct raid5_percpu *percpu; struct raid5_percpu *percpu;
struct flex_array *scribble;
percpu = per_cpu_ptr(conf->percpu, cpu); percpu = per_cpu_ptr(conf->percpu, cpu);
scribble = scribble_alloc(new_disks, err = scribble_alloc(percpu, new_disks,
new_sectors / STRIPE_SECTORS, new_sectors / STRIPE_SECTORS,
GFP_NOIO); GFP_NOIO);
if (err)
if (scribble) {
flex_array_free(percpu->scribble);
percpu->scribble = scribble;
} else {
err = -ENOMEM;
break; break;
} }
}
put_online_cpus(); put_online_cpus();
mddev_resume(conf->mddev); mddev_resume(conf->mddev);
if (!err) { if (!err) {
@ -6742,25 +6732,26 @@ raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks)
static void free_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu) static void free_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu)
{ {
safe_put_page(percpu->spare_page); safe_put_page(percpu->spare_page);
if (percpu->scribble)
flex_array_free(percpu->scribble);
percpu->spare_page = NULL; percpu->spare_page = NULL;
kvfree(percpu->scribble);
percpu->scribble = NULL; percpu->scribble = NULL;
} }
static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu) static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu)
{ {
if (conf->level == 6 && !percpu->spare_page) if (conf->level == 6 && !percpu->spare_page) {
percpu->spare_page = alloc_page(GFP_KERNEL); percpu->spare_page = alloc_page(GFP_KERNEL);
if (!percpu->scribble) if (!percpu->spare_page)
percpu->scribble = scribble_alloc(max(conf->raid_disks, return -ENOMEM;
}
if (scribble_alloc(percpu,
max(conf->raid_disks,
conf->previous_raid_disks), conf->previous_raid_disks),
max(conf->chunk_sectors, max(conf->chunk_sectors,
conf->prev_chunk_sectors) conf->prev_chunk_sectors)
/ STRIPE_SECTORS, / STRIPE_SECTORS,
GFP_KERNEL); GFP_KERNEL)) {
if (!percpu->scribble || (conf->level == 6 && !percpu->spare_page)) {
free_scratch_buffer(conf, percpu); free_scratch_buffer(conf, percpu);
return -ENOMEM; return -ENOMEM;
} }

View File

@ -638,10 +638,11 @@ struct r5conf {
/* per cpu variables */ /* per cpu variables */
struct raid5_percpu { struct raid5_percpu {
struct page *spare_page; /* Used when checking P/Q in raid6 */ struct page *spare_page; /* Used when checking P/Q in raid6 */
struct flex_array *scribble; /* space for constructing buffer void *scribble; /* space for constructing buffer
* lists and performing address * lists and performing address
* conversions * conversions
*/ */
int scribble_obj_size;
} __percpu *percpu; } __percpu *percpu;
int scribble_disks; int scribble_disks;
int scribble_sectors; int scribble_sectors;