This is a note to let you know that I've just added the patch titled dm bufio: avoid a possible __vmalloc deadlock to the 3.4-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: dm-bufio-avoid-a-possible-__vmalloc-deadlock.patch and it can be found in the queue-3.4 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From 4725f1715429f75fa5f053dbe05575d08aeb5967 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka <mpatocka@xxxxxxxxxx> Date: Fri, 10 May 2013 14:37:15 +0100 Subject: dm bufio: avoid a possible __vmalloc deadlock From: Mikulas Patocka <mpatocka@xxxxxxxxxx> commit 502624bdad3dba45dfaacaf36b7d83e39e74b2d2 upstream. This patch uses memalloc_noio_save to avoid a possible deadlock in dm-bufio. (it could happen only with large block size, at most PAGE_SIZE << MAX_ORDER (typically 8MiB). __vmalloc doesn't fully respect gfp flags. The specified gfp flags are used for allocation of requested pages, structures vmap_area, vmap_block and vm_struct and the radix tree nodes. However, the kernel pagetables are allocated always with GFP_KERNEL. Thus the allocation of pagetables can recurse back to the I/O layer and cause a deadlock. This patch uses the function memalloc_noio_save to set per-process PF_MEMALLOC_NOIO flag and the function memalloc_noio_restore to restore it. When this flag is set, all allocations in the process are done with implied GFP_NOIO flag, thus the deadlock can't happen. This should be backported to stable kernels, but they don't have the PF_MEMALLOC_NOIO flag and memalloc_noio_save/memalloc_noio_restore functions. So, PF_MEMALLOC should be set and restored instead. Signed-off-by: Mikulas Patocka <mpatocka@xxxxxxxxxx> Signed-off-by: Alasdair G Kergon <agk@xxxxxxxxxx> [bwh: Backported to 3.2 as recommended] Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> Cc: Rui Xiang <rui.xiang@xxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/md/dm-bufio.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -321,6 +321,9 @@ static void __cache_size_refresh(void) static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask, enum data_mode *data_mode) { + unsigned noio_flag; + void *ptr; + if (c->block_size <= DM_BUFIO_BLOCK_SIZE_SLAB_LIMIT) { *data_mode = DATA_MODE_SLAB; return kmem_cache_alloc(DM_BUFIO_CACHE(c), gfp_mask); @@ -334,7 +337,28 @@ static void *alloc_buffer_data(struct dm } *data_mode = DATA_MODE_VMALLOC; - return __vmalloc(c->block_size, gfp_mask, PAGE_KERNEL); + + /* + * __vmalloc allocates the data pages and auxiliary structures with + * gfp_flags that were specified, but pagetables are always allocated + * with GFP_KERNEL, no matter what was specified as gfp_mask. + * + * Consequently, we must set per-process flag PF_MEMALLOC_NOIO so that + * all allocations done by this process (including pagetables) are done + * as if GFP_NOIO was specified. + */ + + if (gfp_mask & __GFP_NORETRY) { + noio_flag = current->flags & PF_MEMALLOC; + current->flags |= PF_MEMALLOC; + } + + ptr = __vmalloc(c->block_size, gfp_mask, PAGE_KERNEL); + + if (gfp_mask & __GFP_NORETRY) + current->flags = (current->flags & ~PF_MEMALLOC) | noio_flag; + + return ptr; } /* Patches currently in stable-queue which might be from mpatocka@xxxxxxxxxx are queue-3.4/dm-bufio-avoid-a-possible-__vmalloc-deadlock.patch queue-3.4/dm-snapshot-avoid-snapshot-space-leak-on-crash.patch queue-3.4/dm-snapshot-add-missing-module-aliases.patch -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html