Commit 2cda2728 authored by Martin K. Petersen's avatar Martin K. Petersen Committed by Jens Axboe

block: Fix overrun in lcm() and move it to lib

lcm() was defined to take integer-sized arguments.  The supplied
arguments are multiplied, however, causing us to overflow given
sufficiently large input.  That in turn led to incorrect optimal I/O
size reporting in some cases (RAID over RAID).

Switch lcm() over to unsigned long similar to gcd() and move the
function from blk-settings.c to lib.
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent f11c9c5c
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/bootmem.h> /* for max_pfn/max_low_pfn */ #include <linux/bootmem.h> /* for max_pfn/max_low_pfn */
#include <linux/gcd.h> #include <linux/gcd.h>
#include <linux/lcm.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include "blk.h" #include "blk.h"
...@@ -461,16 +462,6 @@ void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b) ...@@ -461,16 +462,6 @@ void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
} }
EXPORT_SYMBOL(blk_queue_stack_limits); EXPORT_SYMBOL(blk_queue_stack_limits);
static unsigned int lcm(unsigned int a, unsigned int b)
{
if (a && b)
return (a * b) / gcd(a, b);
else if (b)
return b;
return a;
}
/** /**
* blk_stack_limits - adjust queue_limits for stacked devices * blk_stack_limits - adjust queue_limits for stacked devices
* @t: the stacking driver limits (top device) * @t: the stacking driver limits (top device)
......
#ifndef _LCM_H
#define _LCM_H
#include <linux/compiler.h>
unsigned long lcm(unsigned long a, unsigned long b) __attribute_const__;
#endif /* _LCM_H */
...@@ -21,7 +21,7 @@ lib-y += kobject.o kref.o klist.o ...@@ -21,7 +21,7 @@ lib-y += kobject.o kref.o klist.o
obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \ bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
string_helpers.o gcd.o list_sort.o string_helpers.o gcd.o lcm.o list_sort.o
ifeq ($(CONFIG_DEBUG_KOBJECT),y) ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG CFLAGS_kobject.o += -DDEBUG
......
#include <linux/kernel.h>
#include <linux/gcd.h>
#include <linux/module.h>
/* Lowest common multiple */
unsigned long lcm(unsigned long a, unsigned long b)
{
if (a && b)
return (a * b) / gcd(a, b);
else if (b)
return b;
return a;
}
EXPORT_SYMBOL_GPL(lcm);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment