summaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorMing Lei <ming.lei@redhat.com>2020-01-11 20:57:43 +0800
committerJens Axboe <axboe@kernel.dk>2020-01-14 13:37:40 -0700
commit4a2f704eb2d831a2d73d7f4cdd54f45c49c3c353 (patch)
tree8ff8c6a1e1c0311dba3b81a9482dc5ea87ed456f /block
parente17016f6dcb047f91a8fc9f46bbf81a21d15ca73 (diff)
downloadlinux-4a2f704eb2d831a2d73d7f4cdd54f45c49c3c353.tar.gz
linux-4a2f704eb2d831a2d73d7f4cdd54f45c49c3c353.tar.bz2
linux-4a2f704eb2d831a2d73d7f4cdd54f45c49c3c353.zip
block: fix get_max_segment_size() overflow on 32bit arch
Commit 429120f3df2d starts to take account of segment's start dma address when computing max segment size, and data type of 'unsigned long' is used to do that. However, the segment mask may be 0xffffffff, so the figured out segment size may be overflowed in case of zero physical address on 32bit arch. Fix the issue by returning queue_max_segment_size() directly when that happens. Fixes: 429120f3df2d ("block: fix splitting segments on boundary masks") Reported-by: Guenter Roeck <linux@roeck-us.net> Tested-by: Guenter Roeck <linux@roeck-us.net> Cc: Christoph Hellwig <hch@lst.de> Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org> Signed-off-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
-rw-r--r--block/blk-merge.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 347782a24a35..1534ed736363 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -164,8 +164,13 @@ static inline unsigned get_max_segment_size(const struct request_queue *q,
unsigned long mask = queue_segment_boundary(q);
offset = mask & (page_to_phys(start_page) + offset);
- return min_t(unsigned long, mask - offset + 1,
- queue_max_segment_size(q));
+
+ /*
+ * overflow may be triggered in case of zero page physical address
+ * on 32bit arch, use queue's max segment size when that happens.
+ */
+ return min_not_zero(mask - offset + 1,
+ (unsigned long)queue_max_segment_size(q));
}
/**