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.
Attachments
Issue Links
- is related to
-
LU-19059 overflow in lov_stripe_size()
-
- Resolved
-
-
LU-9887 sanity-lfsck test_9a: FAIL: (4) Got speed 952, expected less than 144
-
- Resolved
-
-
LU-6163 64-bit divides should use do_div()
-
- Resolved
-
- is related to
-
LU-8137 fix llverdev to be able to write and verify large files in the filesystem
-
- Resolved
-