xen/blkfront: fix memory allocation flags in blkfront_setup_indirect()
Commit1d5c76e664
("xen-blkfront: switch kcalloc to kvcalloc for large array allocation") didn't fix the issue it was meant to, as the flags for allocating the memory are GFP_NOIO, which will lead the memory allocation falling back to kmalloc(). So instead of GFP_NOIO use GFP_KERNEL and do all the memory allocation in blkfront_setup_indirect() in a memalloc_noio_{save,restore} section. Fixes:1d5c76e664
("xen-blkfront: switch kcalloc to kvcalloc for large array allocation") Cc: stable@vger.kernel.org Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Acked-by: Roger Pau Monné <roger.pau@citrix.com> Link: https://lore.kernel.org/r/20200403090034.8753-1-jgross@suse.com Signed-off-by: Juergen Gross <jgross@suse.com>
This commit is contained in:
parent
0102e4efda
commit
3a169c0be7
|
@ -47,6 +47,7 @@
|
|||
#include <linux/bitmap.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/sched/mm.h>
|
||||
|
||||
#include <xen/xen.h>
|
||||
#include <xen/xenbus.h>
|
||||
|
@ -2189,10 +2190,12 @@ static void blkfront_setup_discard(struct blkfront_info *info)
|
|||
|
||||
static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
|
||||
{
|
||||
unsigned int psegs, grants;
|
||||
unsigned int psegs, grants, memflags;
|
||||
int err, i;
|
||||
struct blkfront_info *info = rinfo->dev_info;
|
||||
|
||||
memflags = memalloc_noio_save();
|
||||
|
||||
if (info->max_indirect_segments == 0) {
|
||||
if (!HAS_EXTRA_REQ)
|
||||
grants = BLKIF_MAX_SEGMENTS_PER_REQUEST;
|
||||
|
@ -2224,7 +2227,7 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
|
|||
|
||||
BUG_ON(!list_empty(&rinfo->indirect_pages));
|
||||
for (i = 0; i < num; i++) {
|
||||
struct page *indirect_page = alloc_page(GFP_NOIO);
|
||||
struct page *indirect_page = alloc_page(GFP_KERNEL);
|
||||
if (!indirect_page)
|
||||
goto out_of_memory;
|
||||
list_add(&indirect_page->lru, &rinfo->indirect_pages);
|
||||
|
@ -2235,15 +2238,15 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
|
|||
rinfo->shadow[i].grants_used =
|
||||
kvcalloc(grants,
|
||||
sizeof(rinfo->shadow[i].grants_used[0]),
|
||||
GFP_NOIO);
|
||||
GFP_KERNEL);
|
||||
rinfo->shadow[i].sg = kvcalloc(psegs,
|
||||
sizeof(rinfo->shadow[i].sg[0]),
|
||||
GFP_NOIO);
|
||||
GFP_KERNEL);
|
||||
if (info->max_indirect_segments)
|
||||
rinfo->shadow[i].indirect_grants =
|
||||
kvcalloc(INDIRECT_GREFS(grants),
|
||||
sizeof(rinfo->shadow[i].indirect_grants[0]),
|
||||
GFP_NOIO);
|
||||
GFP_KERNEL);
|
||||
if ((rinfo->shadow[i].grants_used == NULL) ||
|
||||
(rinfo->shadow[i].sg == NULL) ||
|
||||
(info->max_indirect_segments &&
|
||||
|
@ -2252,6 +2255,7 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
|
|||
sg_init_table(rinfo->shadow[i].sg, psegs);
|
||||
}
|
||||
|
||||
memalloc_noio_restore(memflags);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -2271,6 +2275,9 @@ out_of_memory:
|
|||
__free_page(indirect_page);
|
||||
}
|
||||
}
|
||||
|
||||
memalloc_noio_restore(memflags);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue