On Wed, Jan 08, 2020 at 02:38:02AM +0000, Damien Le Moal wrote: > On 2020/01/08 11:34, Jens Axboe wrote: > > On 1/7/20 7:06 PM, Damien Le Moal wrote: > >> On 2020/01/08 10:25, Ming Lei wrote: > >>> 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 because DMA address can > >>> be 64bit on 32bit arch. > >>> > >>> Fixes the issue by using 'unsigned long long' to compute max segment > >>> size. > >>> > >>> Fixes: 429120f3df2d ("block: fix splitting segments on boundary masks") > >>> Reported-by: Guenter Roeck <linux@xxxxxxxxxxxx> > >>> Tested-by: Guenter Roeck <linux@xxxxxxxxxxxx> > >>> Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx> > >>> --- > >>> block/blk-merge.c | 4 ++-- > >>> 1 file changed, 2 insertions(+), 2 deletions(-) > >>> > >>> diff --git a/block/blk-merge.c b/block/blk-merge.c > >>> index 347782a24a35..b0fcc72594cb 100644 > >>> --- a/block/blk-merge.c > >>> +++ b/block/blk-merge.c > >>> @@ -159,12 +159,12 @@ static inline unsigned get_max_io_size(struct request_queue *q, > >>> > >>> static inline unsigned get_max_segment_size(const struct request_queue *q, > >>> struct page *start_page, > >>> - unsigned long offset) > >>> + unsigned long long offset) > >>> { > >>> unsigned long mask = queue_segment_boundary(q); > >>> > >>> offset = mask & (page_to_phys(start_page) + offset); > >> > >> Shouldn't mask be an unsigned long long too for this to give the > >> expected correct result ? > > > > Don't think so, and the seg boundary is a ulong to begin with as well. > > > > I was referring to 32bits arch were ulong is 32bits. So we would have > > offset = 32bits & 64bits; > > with the patch applied. But I am not sure how gcc handles that and if > this can be a problem. Both are 'unsigned', so C compiler will do zero extension for 32bits. Thanks, Ming