plat_idx_to_val() in stat.c has a variable base that is defined as an
unsigned int but it was designed to fit old settings where
FIO_IO_U_PLAT_GROUP_NR = 19.
With the alteration from usec to nsec in commit
d6bb626ef37d3905221ade2887b422717a07af09(nanosecond: update completion
latency recording and normal, json output to use nanoseconds)
FIO_IO_U_PLAT_GROUP_NR is now 29 and the range of latency changed from
uint32_t to uint64_t. This means in plat_idx_to_val(), variable base
can easily exceed a 32-bit range and overflow after error_bits reaches 26.
Eg.
Group MSB #discarded range of #buckets
error_bits value
27 32 26 [
4294967296,
8589934591] 64
base = 1 << (error_bits + FIO_IO_U_PLAT_BITS);
(1 << 32) will overflow
if change to:
base = ((unsigned long long) 1) << (error_bits + FIO_IO_U_PLAT_BITS);
base itself will still overflow
so base should be unsigned long long
*/
static unsigned long long plat_idx_to_val(unsigned int idx)
{
- unsigned int error_bits, k, base;
+ unsigned int error_bits;
+ unsigned long long k, base;
assert(idx < FIO_IO_U_PLAT_NR);
/* Find the group and compute the minimum value of that group */
error_bits = (idx >> FIO_IO_U_PLAT_BITS) - 1;
- base = 1 << (error_bits + FIO_IO_U_PLAT_BITS);
+ base = ((unsigned long long) 1) << (error_bits + FIO_IO_U_PLAT_BITS);
/* Find its bucket number of the group */
k = idx % FIO_IO_U_PLAT_VAL;