| From: Mikulas Patocka <mpatocka@redhat.com> |
| Date: Thu, 31 Oct 2013 13:55:45 -0400 |
| Subject: dm: allocate buffer for messages with small number of arguments using |
| GFP_NOIO |
| |
| commit f36afb3957353d2529cb2b00f78fdccd14fc5e9c upstream. |
| |
| dm-mpath and dm-thin must process messages even if some device is |
| suspended, so we allocate argv buffer with GFP_NOIO. These messages have |
| a small fixed number of arguments. |
| |
| On the other hand, dm-switch needs to process bulk data using messages |
| so excessive use of GFP_NOIO could cause trouble. |
| |
| The patch also lowers the default number of arguments from 64 to 8, so |
| that there is smaller load on GFP_NOIO allocations. |
| |
| Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> |
| Acked-by: Alasdair G Kergon <agk@redhat.com> |
| Signed-off-by: Mike Snitzer <snitzer@redhat.com> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/md/dm-table.c | 18 ++++++++++++++++-- |
| 1 file changed, 16 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/md/dm-table.c |
| +++ b/drivers/md/dm-table.c |
| @@ -581,14 +581,28 @@ static int adjoin(struct dm_table *table |
| |
| /* |
| * Used to dynamically allocate the arg array. |
| + * |
| + * We do first allocation with GFP_NOIO because dm-mpath and dm-thin must |
| + * process messages even if some device is suspended. These messages have a |
| + * small fixed number of arguments. |
| + * |
| + * On the other hand, dm-switch needs to process bulk data using messages and |
| + * excessive use of GFP_NOIO could cause trouble. |
| */ |
| static char **realloc_argv(unsigned *array_size, char **old_argv) |
| { |
| char **argv; |
| unsigned new_size; |
| + gfp_t gfp; |
| |
| - new_size = *array_size ? *array_size * 2 : 64; |
| - argv = kmalloc(new_size * sizeof(*argv), GFP_KERNEL); |
| + if (*array_size) { |
| + new_size = *array_size * 2; |
| + gfp = GFP_KERNEL; |
| + } else { |
| + new_size = 8; |
| + gfp = GFP_NOIO; |
| + } |
| + argv = kmalloc(new_size * sizeof(*argv), gfp); |
| if (argv) { |
| memcpy(argv, old_argv, *array_size * sizeof(*argv)); |
| *array_size = new_size; |