Details
-
Bug
-
Resolution: Fixed
-
Major
-
None
-
None
-
3
-
17275
Description
The Linux do_div() silently truncates divisor to uint32_t, even on x86_64:
25 # define do_div(n,base) ({ \ 26 uint32_t __base = (base);
Any code that uses 64-bit divisor will end up with incorrect result whenever the higher 32 bits aren't all zero. And when the lower 32 bits are all zero, it will end up with a division by zero error.
It happens on both x86_64 and i686. I've verified it on a x86_64 VM.
So any code that looks like the following is BAD:
uint64_t foo, bar; ...... if (bar != 0) do_div(foo, bar);
There seemed to be plenty of such code in Lustre, e.g.:
void fld_cache_fini(struct fld_cache *cache) __u64 pct; ...... if (cache->fci_stat.fst_count > 0) { pct = cache->fci_stat.fst_cache * 100; do_div(pct, cache->fci_stat.fst_count);
I'd suggest to go through and verify all callers of do_div(). In addition, it'd be good to add a warning on do_div() in our patch checker script.