Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f547e7c authored by Juergen Gross's avatar Juergen Gross Committed by Greg Kroah-Hartman
Browse files

xen/blkfront: fix memory allocation flags in blkfront_setup_indirect()



commit 3a169c0be75b59dd85d159493634870cdec6d3c4 upstream.

Commit 1d5c76e664333 ("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: 1d5c76e664333 ("xen-blkfront: switch kcalloc to kvcalloc for large array allocation")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
Reviewed-by: default avatarBoris Ostrovsky <boris.ostrovsky@oracle.com>
Acked-by: default avatarRoger Pau Monné <roger.pau@citrix.com>
Link: https://lore.kernel.org/r/20200403090034.8753-1-jgross@suse.com


Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0721b549
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -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>
@@ -2188,10 +2189,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;
@@ -2223,7 +2226,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);
@@ -2234,15 +2237,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 &&
@@ -2251,6 +2254,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;

@@ -2270,6 +2274,9 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
			__free_page(indirect_page);
		}
	}

	memalloc_noio_restore(memflags);

	return -ENOMEM;
}