From: Greg Kroah-Hartman Date: Thu, 20 Mar 2014 18:42:35 +0000 (-0700) Subject: 3.10-stable patches X-Git-Tag: v3.4.84~15 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=15bc1206458b5000d1d0e1bd43bfac5e696fae5b;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: dm-cache-fix-access-beyond-end-of-origin-device.patch dm-cache-fix-truncation-bug-when-copying-a-block-to-from-2tb-fast-device.patch mm-compaction-break-out-of-loop-on-pagebuddy-in-isolate_freepages_block.patch --- diff --git a/queue-3.10/dm-cache-fix-access-beyond-end-of-origin-device.patch b/queue-3.10/dm-cache-fix-access-beyond-end-of-origin-device.patch new file mode 100644 index 00000000000..86bf34ecc61 --- /dev/null +++ b/queue-3.10/dm-cache-fix-access-beyond-end-of-origin-device.patch @@ -0,0 +1,62 @@ +From e893fba90c09f9b57fb97daae204ea9cc2c52fa5 Mon Sep 17 00:00:00 2001 +From: Heinz Mauelshagen +Date: Wed, 12 Mar 2014 16:13:39 +0100 +Subject: dm cache: fix access beyond end of origin device + +From: Heinz Mauelshagen + +commit e893fba90c09f9b57fb97daae204ea9cc2c52fa5 upstream. + +In order to avoid wasting cache space a partial block at the end of the +origin device is not cached. Unfortunately, the check for such a +partial block at the end of the origin device was flawed. + +Fix accesses beyond the end of the origin device that occured due to +attempted promotion of an undetected partial block by: + +- initializing the per bio data struct to allow cache_end_io to work properly +- recognizing access to the partial block at the end of the origin device +- avoiding out of bounds access to the discard bitset + +Otherwise, users can experience errors like the following: + + attempt to access beyond end of device + dm-5: rw=0, want=20971520, limit=20971456 + ... + device-mapper: cache: promotion failed; couldn't copy block + +Signed-off-by: Heinz Mauelshagen +Acked-by: Joe Thornber +Signed-off-by: Mike Snitzer +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-cache-target.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/md/dm-cache-target.c ++++ b/drivers/md/dm-cache-target.c +@@ -2175,20 +2175,18 @@ static int cache_map(struct dm_target *t + bool discarded_block; + struct dm_bio_prison_cell *cell; + struct policy_result lookup_result; +- struct per_bio_data *pb; ++ struct per_bio_data *pb = init_per_bio_data(bio, pb_data_size); + +- if (from_oblock(block) > from_oblock(cache->origin_blocks)) { ++ if (unlikely(from_oblock(block) >= from_oblock(cache->origin_blocks))) { + /* + * This can only occur if the io goes to a partial block at + * the end of the origin device. We don't cache these. + * Just remap to the origin and carry on. + */ +- remap_to_origin_clear_discard(cache, bio, block); ++ remap_to_origin(cache, bio); + return DM_MAPIO_REMAPPED; + } + +- pb = init_per_bio_data(bio, pb_data_size); +- + if (bio->bi_rw & (REQ_FLUSH | REQ_FUA | REQ_DISCARD)) { + defer_bio(cache, bio); + return DM_MAPIO_SUBMITTED; diff --git a/queue-3.10/dm-cache-fix-truncation-bug-when-copying-a-block-to-from-2tb-fast-device.patch b/queue-3.10/dm-cache-fix-truncation-bug-when-copying-a-block-to-from-2tb-fast-device.patch new file mode 100644 index 00000000000..802c4eb9e5f --- /dev/null +++ b/queue-3.10/dm-cache-fix-truncation-bug-when-copying-a-block-to-from-2tb-fast-device.patch @@ -0,0 +1,48 @@ +From 8b9d96666529a979acf4825391efcc7c8a3e9f12 Mon Sep 17 00:00:00 2001 +From: Heinz Mauelshagen +Date: Wed, 12 Mar 2014 00:40:05 +0100 +Subject: dm cache: fix truncation bug when copying a block to/from >2TB fast device + +From: Heinz Mauelshagen + +commit 8b9d96666529a979acf4825391efcc7c8a3e9f12 upstream. + +During demotion or promotion to a cache's >2TB fast device we must not +truncate the cache block's associated sector to 32bits. The 32bit +temporary result of from_cblock() caused a 32bit multiplication when +calculating the sector of the fast device in issue_copy_real(). + +Use an intermediate 64bit type to store the 32bit from_cblock() to allow +for proper 64bit multiplication. + +Here is an example of how this bug manifests on an ext4 filesystem: + + EXT4-fs error (device dm-0): ext4_mb_generate_buddy:756: group 17136, 32768 clusters in bitmap, 30688 in gd; block bitmap corrupt. + JBD2: Spotted dirty metadata buffer (dev = dm-0, blocknr = 0). There's a risk of filesystem corruption in case of system crash. + +Signed-off-by: Heinz Mauelshagen +Acked-by: Joe Thornber +Signed-off-by: Mike Snitzer +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-cache-target.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/md/dm-cache-target.c ++++ b/drivers/md/dm-cache-target.c +@@ -861,12 +861,13 @@ static void issue_copy_real(struct dm_ca + int r; + struct dm_io_region o_region, c_region; + struct cache *cache = mg->cache; ++ sector_t cblock = from_cblock(mg->cblock); + + o_region.bdev = cache->origin_dev->bdev; + o_region.count = cache->sectors_per_block; + + c_region.bdev = cache->cache_dev->bdev; +- c_region.sector = from_cblock(mg->cblock) * cache->sectors_per_block; ++ c_region.sector = cblock * cache->sectors_per_block; + c_region.count = cache->sectors_per_block; + + if (mg->writeback || mg->demote) { diff --git a/queue-3.10/mm-compaction-break-out-of-loop-on-pagebuddy-in-isolate_freepages_block.patch b/queue-3.10/mm-compaction-break-out-of-loop-on-pagebuddy-in-isolate_freepages_block.patch new file mode 100644 index 00000000000..3eccade0932 --- /dev/null +++ b/queue-3.10/mm-compaction-break-out-of-loop-on-pagebuddy-in-isolate_freepages_block.patch @@ -0,0 +1,120 @@ +From 2af120bc040c5ebcda156df6be6a66610ab6957f Mon Sep 17 00:00:00 2001 +From: Laura Abbott +Date: Mon, 10 Mar 2014 15:49:44 -0700 +Subject: mm/compaction: break out of loop on !PageBuddy in isolate_freepages_block + +From: Laura Abbott + +commit 2af120bc040c5ebcda156df6be6a66610ab6957f upstream. + +We received several reports of bad page state when freeing CMA pages +previously allocated with alloc_contig_range: + + BUG: Bad page state in process Binder_A pfn:63202 + page:d21130b0 count:0 mapcount:1 mapping: (null) index:0x7dfbf + page flags: 0x40080068(uptodate|lru|active|swapbacked) + +Based on the page state, it looks like the page was still in use. The +page flags do not make sense for the use case though. Further debugging +showed that despite alloc_contig_range returning success, at least one +page in the range still remained in the buddy allocator. + +There is an issue with isolate_freepages_block. In strict mode (which +CMA uses), if any pages in the range cannot be isolated, +isolate_freepages_block should return failure 0. The current check +keeps track of the total number of isolated pages and compares against +the size of the range: + + if (strict && nr_strict_required > total_isolated) + total_isolated = 0; + +After taking the zone lock, if one of the pages in the range is not in +the buddy allocator, we continue through the loop and do not increment +total_isolated. If in the last iteration of the loop we isolate more +than one page (e.g. last page needed is a higher order page), the check +for total_isolated may pass and we fail to detect that a page was +skipped. The fix is to bail out if the loop immediately if we are in +strict mode. There's no benfit to continuing anyway since we need all +pages to be isolated. Additionally, drop the error checking based on +nr_strict_required and just check the pfn ranges. This matches with +what isolate_freepages_range does. + +Signed-off-by: Laura Abbott +Acked-by: Minchan Kim +Cc: Mel Gorman +Acked-by: Vlastimil Babka +Cc: Joonsoo Kim +Acked-by: Bartlomiej Zolnierkiewicz +Acked-by: Michal Nazarewicz +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/compaction.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +--- a/mm/compaction.c ++++ b/mm/compaction.c +@@ -252,7 +252,6 @@ static unsigned long isolate_freepages_b + { + int nr_scanned = 0, total_isolated = 0; + struct page *cursor, *valid_page = NULL; +- unsigned long nr_strict_required = end_pfn - blockpfn; + unsigned long flags; + bool locked = false; + +@@ -265,11 +264,12 @@ static unsigned long isolate_freepages_b + + nr_scanned++; + if (!pfn_valid_within(blockpfn)) +- continue; ++ goto isolate_fail; ++ + if (!valid_page) + valid_page = page; + if (!PageBuddy(page)) +- continue; ++ goto isolate_fail; + + /* + * The zone lock must be held to isolate freepages. +@@ -290,12 +290,10 @@ static unsigned long isolate_freepages_b + + /* Recheck this is a buddy page under lock */ + if (!PageBuddy(page)) +- continue; ++ goto isolate_fail; + + /* Found a free page, break it into order-0 pages */ + isolated = split_free_page(page); +- if (!isolated && strict) +- break; + total_isolated += isolated; + for (i = 0; i < isolated; i++) { + list_add(&page->lru, freelist); +@@ -306,7 +304,15 @@ static unsigned long isolate_freepages_b + if (isolated) { + blockpfn += isolated - 1; + cursor += isolated - 1; ++ continue; + } ++ ++isolate_fail: ++ if (strict) ++ break; ++ else ++ continue; ++ + } + + trace_mm_compaction_isolate_freepages(nr_scanned, total_isolated); +@@ -316,7 +322,7 @@ static unsigned long isolate_freepages_b + * pages requested were isolated. If there were any failures, 0 is + * returned and CMA will fail. + */ +- if (strict && nr_strict_required > total_isolated) ++ if (strict && blockpfn < end_pfn) + total_isolated = 0; + + if (locked) diff --git a/queue-3.10/series b/queue-3.10/series index ba524ae3ac6..4c4f8035e39 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -59,3 +59,6 @@ kvm-svm-fix-cr8-intercept-window.patch pci-enable-intx-in-pci_reenable_device-only-when-msi-msi-x-not-enabled.patch vmxnet3-fix-netpoll-race-condition.patch vmxnet3-fix-building-without-config_pci_msi.patch +mm-compaction-break-out-of-loop-on-pagebuddy-in-isolate_freepages_block.patch +dm-cache-fix-truncation-bug-when-copying-a-block-to-from-2tb-fast-device.patch +dm-cache-fix-access-beyond-end-of-origin-device.patch