Skip to content

Commit

Permalink
block: Fix overrun in lcm() and move it to lib
Browse files Browse the repository at this point in the history
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: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
  • Loading branch information
Martin K. Petersen authored and Jens Axboe committed Mar 15, 2010
1 parent f11c9c5 commit 2cda272
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 11 deletions.
11 changes: 1 addition & 10 deletions block/blk-settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <linux/blkdev.h>
#include <linux/bootmem.h> /* for max_pfn/max_low_pfn */
#include <linux/gcd.h>
#include <linux/lcm.h>
#include <linux/jiffies.h>

#include "blk.h"
Expand Down Expand Up @@ -461,16 +462,6 @@ void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
}
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
* @t: the stacking driver limits (top device)
Expand Down
8 changes: 8 additions & 0 deletions include/linux/lcm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _LCM_H
#define _LCM_H

#include <linux/compiler.h>

unsigned long lcm(unsigned long a, unsigned long b) __attribute_const__;

#endif /* _LCM_H */
2 changes: 1 addition & 1 deletion lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
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)
CFLAGS_kobject.o += -DDEBUG
Expand Down
15 changes: 15 additions & 0 deletions lib/lcm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#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);

0 comments on commit 2cda272

Please sign in to comment.