aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/dm-bufio.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index c6083132c4b8..0387e05cdb98 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -319,6 +319,9 @@ static void __cache_size_refresh(void)
319static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask, 319static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
320 enum data_mode *data_mode) 320 enum data_mode *data_mode)
321{ 321{
322 unsigned noio_flag;
323 void *ptr;
324
322 if (c->block_size <= DM_BUFIO_BLOCK_SIZE_SLAB_LIMIT) { 325 if (c->block_size <= DM_BUFIO_BLOCK_SIZE_SLAB_LIMIT) {
323 *data_mode = DATA_MODE_SLAB; 326 *data_mode = DATA_MODE_SLAB;
324 return kmem_cache_alloc(DM_BUFIO_CACHE(c), gfp_mask); 327 return kmem_cache_alloc(DM_BUFIO_CACHE(c), gfp_mask);
@@ -332,7 +335,26 @@ static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
332 } 335 }
333 336
334 *data_mode = DATA_MODE_VMALLOC; 337 *data_mode = DATA_MODE_VMALLOC;
335 return __vmalloc(c->block_size, gfp_mask, PAGE_KERNEL); 338
339 /*
340 * __vmalloc allocates the data pages and auxiliary structures with
341 * gfp_flags that were specified, but pagetables are always allocated
342 * with GFP_KERNEL, no matter what was specified as gfp_mask.
343 *
344 * Consequently, we must set per-process flag PF_MEMALLOC_NOIO so that
345 * all allocations done by this process (including pagetables) are done
346 * as if GFP_NOIO was specified.
347 */
348
349 if (gfp_mask & __GFP_NORETRY)
350 noio_flag = memalloc_noio_save();
351
352 ptr = __vmalloc(c->block_size, gfp_mask, PAGE_KERNEL);
353
354 if (gfp_mask & __GFP_NORETRY)
355 memalloc_noio_restore(noio_flag);
356
357 return ptr;
336} 358}
337 359
338/* 360/*