summaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorDamien Le Moal <damien.lemoal@wdc.com>2021-06-19 08:15:19 +0900
committerMike Snitzer <snitzer@redhat.com>2021-06-25 15:25:23 -0400
commit28436ba34b7d1b6af2a898d37ee678a1eb643db4 (patch)
tree3249cac7d6ca1cf1def45ff7937a258ccec8fe3b /drivers/md
parent326dbde2e0a77be107c9ddd04899fd9ee27ffc94 (diff)
downloadlinux-28436ba34b7d1b6af2a898d37ee678a1eb643db4.tar.bz2
dm zone: fix dm_revalidate_zones() memory allocation
Make sure that the zone write pointer offset array is allocated with a vmalloc in dm_zone_revalidate_cb() by passing GFP_KERNEL gfp flag to kvcalloc(). However, since we do not want to trigger IOs while revalidating zones, change dm_revalidate_zones() to have the zone scan done in GFP_NOIO context using memalloc_noio_save/restore calls. Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Fixes: bb37d77239af ("dm: introduce zone append emulation") Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-zone.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c
index c2f26949f5ee..6d82a34438c8 100644
--- a/drivers/md/dm-zone.c
+++ b/drivers/md/dm-zone.c
@@ -205,7 +205,7 @@ static int dm_zone_revalidate_cb(struct blk_zone *zone, unsigned int idx,
if (!md->zwp_offset) {
md->zwp_offset =
kvcalloc(q->nr_zones, sizeof(unsigned int),
- GFP_NOIO);
+ GFP_KERNEL);
if (!md->zwp_offset)
return -ENOMEM;
}
@@ -230,6 +230,7 @@ static int dm_zone_revalidate_cb(struct blk_zone *zone, unsigned int idx,
static int dm_revalidate_zones(struct mapped_device *md, struct dm_table *t)
{
struct request_queue *q = md->queue;
+ unsigned int noio_flag;
int ret;
/*
@@ -241,9 +242,14 @@ static int dm_revalidate_zones(struct mapped_device *md, struct dm_table *t)
if (md->nr_zones)
return 0;
- /* Scan all zones to initialize everything */
+ /*
+ * Scan all zones to initialize everything. Ensure that all vmalloc
+ * operations in this context are done as if GFP_NOIO was specified.
+ */
+ noio_flag = memalloc_noio_save();
ret = dm_blk_do_report_zones(md, t, 0, q->nr_zones,
dm_zone_revalidate_cb, md);
+ memalloc_noio_restore(noio_flag);
if (ret < 0)
goto err;
if (ret != q->nr_zones) {