From: Greg Kroah-Hartman Date: Mon, 27 Nov 2017 13:20:40 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v3.18.85~33 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e37d228c744d17df0ceece9fd2c14745c0b1671a;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: dm-allocate-struct-mapped_device-with-kvzalloc.patch dm-bufio-fix-integer-overflow-when-limiting-maximum-cache-size.patch --- diff --git a/queue-4.9/dm-allocate-struct-mapped_device-with-kvzalloc.patch b/queue-4.9/dm-allocate-struct-mapped_device-with-kvzalloc.patch new file mode 100644 index 00000000000..55117e12fe3 --- /dev/null +++ b/queue-4.9/dm-allocate-struct-mapped_device-with-kvzalloc.patch @@ -0,0 +1,91 @@ +From 856eb0916d181da6d043cc33e03f54d5c5bbe54a Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Tue, 31 Oct 2017 19:33:02 -0400 +Subject: dm: allocate struct mapped_device with kvzalloc + +From: Mikulas Patocka + +commit 856eb0916d181da6d043cc33e03f54d5c5bbe54a upstream. + +The structure srcu_struct can be very big, its size is proportional to the +value CONFIG_NR_CPUS. The Fedora kernel has CONFIG_NR_CPUS 8192, the field +io_barrier in the struct mapped_device has 84kB in the debugging kernel +and 50kB in the non-debugging kernel. The large size may result in failure +of the function kzalloc_node. + +In order to avoid the allocation failure, we use the function +kvzalloc_node, this function falls back to vmalloc if a large contiguous +chunk of memory is not available. This patch also moves the field +io_barrier to the last position of struct mapped_device - the reason is +that on many processor architectures, short memory offsets result in +smaller code than long memory offsets - on x86-64 it reduces code size by +320 bytes. + +Note to stable kernel maintainers - the kernels 4.11 and older don't have +the function kvzalloc_node, you can use the function vzalloc_node instead. + +Signed-off-by: Mikulas Patocka +Signed-off-by: Mike Snitzer +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-core.h | 3 ++- + drivers/md/dm.c | 7 ++++--- + 2 files changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/md/dm-core.h ++++ b/drivers/md/dm-core.h +@@ -29,7 +29,6 @@ struct dm_kobject_holder { + * DM targets must _not_ deference a mapped_device to directly access its members! + */ + struct mapped_device { +- struct srcu_struct io_barrier; + struct mutex suspend_lock; + + /* +@@ -127,6 +126,8 @@ struct mapped_device { + struct blk_mq_tag_set *tag_set; + bool use_blk_mq:1; + bool init_tio_pdu:1; ++ ++ struct srcu_struct io_barrier; + }; + + void dm_init_md_queue(struct mapped_device *md); +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #define DM_MSG_PREFIX "core" + +@@ -1511,7 +1512,7 @@ static struct mapped_device *alloc_dev(i + struct mapped_device *md; + void *old_md; + +- md = kzalloc_node(sizeof(*md), GFP_KERNEL, numa_node_id); ++ md = vzalloc_node(sizeof(*md), numa_node_id); + if (!md) { + DMWARN("unable to allocate device, out of memory."); + return NULL; +@@ -1605,7 +1606,7 @@ bad_io_barrier: + bad_minor: + module_put(THIS_MODULE); + bad_module_get: +- kfree(md); ++ kvfree(md); + return NULL; + } + +@@ -1624,7 +1625,7 @@ static void free_dev(struct mapped_devic + free_minor(minor); + + module_put(THIS_MODULE); +- kfree(md); ++ kvfree(md); + } + + static void __bind_mempools(struct mapped_device *md, struct dm_table *t) diff --git a/queue-4.9/dm-bufio-fix-integer-overflow-when-limiting-maximum-cache-size.patch b/queue-4.9/dm-bufio-fix-integer-overflow-when-limiting-maximum-cache-size.patch new file mode 100644 index 00000000000..0ea7bbd4268 --- /dev/null +++ b/queue-4.9/dm-bufio-fix-integer-overflow-when-limiting-maximum-cache-size.patch @@ -0,0 +1,72 @@ +From 74d4108d9e681dbbe4a2940ed8fdff1f6868184c Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Wed, 15 Nov 2017 16:38:09 -0800 +Subject: dm bufio: fix integer overflow when limiting maximum cache size + +From: Eric Biggers + +commit 74d4108d9e681dbbe4a2940ed8fdff1f6868184c upstream. + +The default max_cache_size_bytes for dm-bufio is meant to be the lesser +of 25% of the size of the vmalloc area and 2% of the size of lowmem. +However, on 32-bit systems the intermediate result in the expression + + (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100 + +overflows, causing the wrong result to be computed. For example, on a +32-bit system where the vmalloc area is 520093696 bytes, the result is +1174405 rather than the expected 130023424, which makes the maximum +cache size much too small (far less than 2% of lowmem). This causes +severe performance problems for dm-verity users on affected systems. + +Fix this by using mult_frac() to correctly multiply by a percentage. Do +this for all places in dm-bufio that multiply by a percentage. Also +replace (VMALLOC_END - VMALLOC_START) with VMALLOC_TOTAL, which contrary +to the comment is now defined in include/linux/vmalloc.h. + +Depends-on: 9993bc635 ("sched/x86: Fix overflow in cyc2ns_offset") +Fixes: 95d402f057f2 ("dm: add bufio") +Signed-off-by: Eric Biggers +Signed-off-by: Mike Snitzer +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-bufio.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +--- a/drivers/md/dm-bufio.c ++++ b/drivers/md/dm-bufio.c +@@ -937,7 +937,8 @@ static void __get_memory_limit(struct dm + buffers = c->minimum_buffers; + + *limit_buffers = buffers; +- *threshold_buffers = buffers * DM_BUFIO_WRITEBACK_PERCENT / 100; ++ *threshold_buffers = mult_frac(buffers, ++ DM_BUFIO_WRITEBACK_PERCENT, 100); + } + + /* +@@ -1856,19 +1857,15 @@ static int __init dm_bufio_init(void) + memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches); + memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names); + +- mem = (__u64)((totalram_pages - totalhigh_pages) * +- DM_BUFIO_MEMORY_PERCENT / 100) << PAGE_SHIFT; ++ mem = (__u64)mult_frac(totalram_pages - totalhigh_pages, ++ DM_BUFIO_MEMORY_PERCENT, 100) << PAGE_SHIFT; + + if (mem > ULONG_MAX) + mem = ULONG_MAX; + + #ifdef CONFIG_MMU +- /* +- * Get the size of vmalloc space the same way as VMALLOC_TOTAL +- * in fs/proc/internal.h +- */ +- if (mem > (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100) +- mem = (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100; ++ if (mem > mult_frac(VMALLOC_TOTAL, DM_BUFIO_VMALLOC_PERCENT, 100)) ++ mem = mult_frac(VMALLOC_TOTAL, DM_BUFIO_VMALLOC_PERCENT, 100); + #endif + + dm_bufio_default_cache_size = mem; diff --git a/queue-4.9/series b/queue-4.9/series index 4e9ef8e0d09..4520eff3a4d 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -17,3 +17,5 @@ mips-ralink-fix-mt7628-pinmux.patch mips-ralink-fix-typo-in-mt7628-pinmux-function.patch pci-set-cavium-acs-capability-quirk-flags-to-assert-rr-cr-sv-uf.patch alsa-hda-add-raven-pci-id.patch +dm-bufio-fix-integer-overflow-when-limiting-maximum-cache-size.patch +dm-allocate-struct-mapped_device-with-kvzalloc.patch