include/linux/math.h: fix mult_frac() multiple argument evaluation bug
authorAlexey Dobriyan <adobriyan@gmail.com>
Sat, 20 May 2023 18:25:19 +0000 (21:25 +0300)
committerAndrew Morton <akpm@linux-foundation.org>
Sat, 10 Jun 2023 00:44:22 +0000 (17:44 -0700)
mult_frac() evaluates _all_ arguments multiple times in the body.

Clarify comment while I'm at it.

Link: https://lkml.kernel.org/r/f9f9fdbb-ec8e-4f5e-a998-2a58627a1a43@p183
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
include/linux/math.h

index 439b8f0..2d38865 100644 (file)
@@ -118,17 +118,17 @@ __STRUCT_FRACT(s32)
 __STRUCT_FRACT(u32)
 #undef __STRUCT_FRACT
 
-/*
- * Multiplies an integer by a fraction, while avoiding unnecessary
- * overflow or loss of precision.
- */
-#define mult_frac(x, numer, denom)(                    \
-{                                                      \
-       typeof(x) quot = (x) / (denom);                 \
-       typeof(x) rem  = (x) % (denom);                 \
-       (quot * (numer)) + ((rem * (numer)) / (denom)); \
-}                                                      \
-)
+/* Calculate "x * n / d" without unnecessary overflow or loss of precision. */
+#define mult_frac(x, n, d)     \
+({                             \
+       typeof(x) x_ = (x);     \
+       typeof(n) n_ = (n);     \
+       typeof(d) d_ = (d);     \
+                               \
+       typeof(x_) q = x_ / d_; \
+       typeof(x_) r = x_ % d_; \
+       q * n_ + r * n_ / d_;   \
+})
 
 #define sector_div(a, b) do_div(a, b)