From 1b4ad25e2f29172c86d3293b61f0c5232d4a2da8 Mon Sep 17 00:00:00 2001 From: Alex Zhuravlev Date: Wed, 2 Jun 2010 22:01:14 -0700 Subject: [PATCH] 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 --- module/spl/spl-generic.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/module/spl/spl-generic.c b/module/spl/spl-generic.c index 29b698889e..9916051de0 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 */