Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2013-04-02 15:01:38 +0200
committerJiri Kosina <jkosina@suse.cz>2013-04-02 15:01:38 +0200
commit25ae5d24433cc53a1c4e8953205d61215b58345f (patch)
treebb41e441f70f979c1f42dfbb2d7749f7db2a3f3a
parent1b28ed1fb231b277a06ec6efac6f638d876c51eb (diff)
blk: avoid divide-by-zero with zero discard granularityrpm-3.0.70-0.9
-rw-r--r--patches.fixes/blk-avoid-divide-by-zero-with-zero-discard-granulari.patch79
-rw-r--r--series.conf1
2 files changed, 80 insertions, 0 deletions
diff --git a/patches.fixes/blk-avoid-divide-by-zero-with-zero-discard-granulari.patch b/patches.fixes/blk-avoid-divide-by-zero-with-zero-discard-granulari.patch
new file mode 100644
index 0000000000..10d49270fc
--- /dev/null
+++ b/patches.fixes/blk-avoid-divide-by-zero-with-zero-discard-granulari.patch
@@ -0,0 +1,79 @@
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Subject: [PATCH] blk: avoid divide-by-zero with zero discard granularity
+Patch-mainline: 59771079c18c44e39106f0f30054025acafadb41
+References: bnc#812935
+
+Commit 8dd2cb7e880d ("block: discard granularity might not be power of
+2") changed a couple of 'binary and' operations into modulus operations.
+Which turned the harmless case of a zero discard_granularity into a
+possible divide-by-zero.
+
+The code also had a much more subtle bug: it was doing the modulus of a
+value in bytes using 'sector_t'. That was always conceptually wrong,
+but didn't actually matter back when the code assumed a power-of-two
+granularity: we only looked at the low bits anyway.
+
+But with potentially arbitrary sector numbers, using a 'sector_t' to
+express bytes is very very wrong: depending on configuration it limits
+the starting offset of the device to just 32 bits, and any overflow
+would result in a wrong value if the modulus wasn't a power-of-two.
+
+So re-write the code to not only protect against the divide-by-zero, but
+to do the starting sector arithmetic in sectors, and using the proper
+types.
+
+[ For any mathematicians out there: it also looks monumentally stupid to
+ do the 'modulo granularity' operation *twice*, never mind having a "+
+ granularity" in the second modulus op.
+
+ But that's the easiest way to avoid negative values or overflow, and
+ it is how the original code was done. ]
+
+Reported-by: Ingo Molnar <mingo@kernel.org>
+Reported-by: Doug Anderson <dianders@chromium.org>
+Cc: Neil Brown <neilb@suse.de>
+Cc: Shaohua Li <shli@fusionio.com>
+Acked-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Acked-by: Jiri Kosina <jkosina@suse.cz>
+---
+ include/linux/blkdev.h | 19 +++++++++++++++----
+ 1 files changed, 15 insertions(+), 4 deletions(-)
+
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index acb4f7b..f94bc83 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -1188,14 +1188,25 @@ static inline int queue_discard_alignment(struct request_queue *q)
+
+ static inline int queue_limit_discard_alignment(struct queue_limits *lim, sector_t sector)
+ {
+- sector_t alignment = sector << 9;
+- alignment = sector_div(alignment, lim->discard_granularity);
++ unsigned int alignment, granularity, offset;
+
+ if (!lim->max_discard_sectors)
+ return 0;
+
+- alignment = lim->discard_granularity + lim->discard_alignment - alignment;
+- return sector_div(alignment, lim->discard_granularity);
++ /* Why are these in bytes, not sectors? */
++ alignment = lim->discard_alignment >> 9;
++ granularity = lim->discard_granularity >> 9;
++ if (!granularity)
++ return 0;
++
++ /* Offset of the partition start in 'granularity' sectors */
++ offset = sector_div(sector, granularity);
++
++ /* And why do we do this modulus *again* in blkdev_issue_discard()? */
++ offset = (granularity + alignment - offset) % granularity;
++
++ /* Turn it back into bytes, gaah */
++ return offset << 9;
+ }
+
+ static inline int bdev_discard_alignment(struct block_device *bdev)
+--
+1.7.8.3
+
diff --git a/series.conf b/series.conf
index 0cf614e743..aa2671954a 100644
--- a/series.conf
+++ b/series.conf
@@ -1276,6 +1276,7 @@
patches.fixes/block-Make-blk_cleanup_queue-wait-until-request_fn-f.patch
patches.fixes/block-discard-granularity-might-not-be-power-of-2.patch
patches.fixes/block-add-plug-for-blkdev_issue_discard.patch
+ patches.fixes/blk-avoid-divide-by-zero-with-zero-discard-granulari.patch
########################################################
# Networking, IPv6