diff options
author | Alex Zhuravlev <[email protected]> | 2010-06-02 22:01:14 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2010-06-03 09:06:55 -0700 |
commit | 1b4ad25e2f29172c86d3293b61f0c5232d4a2da8 (patch) | |
tree | cff3cadd022593ccb32692843bb9b5382af41b7e | |
parent | 8a1c9a02fb66ac5885990ec4d82faf03f820085b (diff) |
Stack overflow on 64-bit modulus operations on 32-bit architectures.
Running 'zpool create' on a 32-bit machine with an SPL compiled with
gcc 4.4.4 led to a stack overlow. This turned out to be due to some
sort of 'optimization' by gcc:
uint64_t __umoddi3(uint64_t dividend, uint64_t divisor)
{
return dividend - divisor * (dividend / divisor);
}
This code was supposed to be using __udivdi3 to implement /, but gcc
instead implemented it via __umoddi3 itself.
Signed-off-by: Brian Behlendorf <[email protected]>
-rw-r--r-- | module/spl/spl-generic.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/module/spl/spl-generic.c b/module/spl/spl-generic.c index 29b698889..9916051de 100644 --- a/module/spl/spl-generic.c +++ b/module/spl/spl-generic.c @@ -96,7 +96,8 @@ EXPORT_SYMBOL(highbit); * Implementation of 64 bit division for 32-bit machines. */ #if BITS_PER_LONG == 32 -uint64_t __udivdi3(uint64_t dividend, uint64_t divisor) +uint64_t +__udivdi3(uint64_t dividend, uint64_t divisor) { #if defined(HAVE_DIV64_64) /* 2.6.22 - 2.6.25 API */ return div64_64(dividend, divisor); @@ -125,9 +126,10 @@ EXPORT_SYMBOL(__udivdi3); /* * Implementation of 64 bit modulo for 32-bit machines. */ -uint64_t __umoddi3(uint64_t dividend, uint64_t divisor) +uint64_t +__umoddi3(uint64_t dividend, uint64_t divisor) { - return dividend - divisor * (dividend / divisor); + return (dividend - (divisor * __udivdi3(dividend, divisor))); } EXPORT_SYMBOL(__umoddi3); #endif /* BITS_PER_LONG */ |