diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-09-28 17:38:08 +0400 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-09-28 17:38:08 +0400 |
commit | 920c52a5c80969ab0c831e56cb26971e83942f0a (patch) | |
tree | 5aa610db0c52265c4dac61d453990bf3b875d933 /miscutils/hdparm.c | |
parent | a0ad43b80b4a70a243b17ec464a194cf8369a940 (diff) |
hdparm: more robust (re overflows) code. +38 bytes.
Diffstat (limited to 'miscutils/hdparm.c')
-rw-r--r-- | miscutils/hdparm.c | 48 |
1 files changed, 23 insertions, 25 deletions
diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c index 1f85644d6..906dd7a0c 100644 --- a/miscutils/hdparm.c +++ b/miscutils/hdparm.c @@ -1353,35 +1353,34 @@ static void read_big_block(/*int fd,*/ char *buf) buf[i] &= 1; } -static unsigned long long dev_size_mb(/*int fd*/ void) +static unsigned dev_size_mb(/*int fd*/ void) { union { unsigned long long blksize64; unsigned blksize32; } u; - if (0 == ioctl(fd, BLKGETSIZE64, &u.blksize64)) { // returns bytes - return u.blksize64 / (1024 * 1024); + if (0 == ioctl(fd, BLKGETSIZE64, &u.blksize64)) { // bytes + u.blksize64 /= (1024 * 1024); + } else { + xioctl(fd, BLKGETSIZE, &u.blksize32); // sectors + u.blksize64 = u.blksize32 / (2 * 1024); } - xioctl(fd, BLKGETSIZE, &u.blksize32); // returns sectors - return u.blksize32 / (2 * 1024); + if (u.blksize64 > UINT_MAX) + return UINT_MAX; + return u.blksize64; } -static void print_timing(unsigned long m, unsigned elapsed_us) +static void print_timing(unsigned m, unsigned elapsed_us) { unsigned sec = elapsed_us / 1000000; unsigned hs = (elapsed_us % 1000000) / 10000; - printf("%5lu MB in %u.%02u seconds = %lu kB/s\n", + printf("%5u MB in %u.%02u seconds = %u kB/s\n", m, sec, hs, - /* Trying to not overflow 32-bit arith in m * CONST - * by keeping CONST not so big. But elapsed_us / CONST2 - * also should not introduce big errors. Currently, - * 16000us is ~1.6% of 1 second. - * "+ 1" prevents div-by-0. */ - (m * (1024 * 1000000 / (16*1024))) / (elapsed_us / (16*1024) + 1) - // ~= (m * 1024 * 1000000) / elapsed_us - // = (m * 1024) / (elapsed_us / 1000000) + /* + 1 prevents div-by-0 */ + (unsigned) ((unsigned long long)m * (1024 * 1000000) / (elapsed_us + 1)) + // ~= (m * 1024) / (elapsed_us / 1000000) // = kb / elapsed_sec ); } @@ -1392,19 +1391,14 @@ static void do_time(int cache /*,int fd*/) */ { unsigned max_iterations, iterations; - unsigned start; /* don't need to be long long */ + unsigned start; /* doesn't need to be long long */ unsigned elapsed, elapsed2; - unsigned long total_MB; + unsigned total_MB; char *buf = xmalloc(TIMING_BUF_BYTES); if (mlock(buf, TIMING_BUF_BYTES)) bb_perror_msg_and_die("mlock"); - /* Don't want to read past the end! */ - max_iterations = UINT_MAX; - if (!cache) - max_iterations = dev_size_mb() / TIMING_BUF_MB; - /* Clear out the device request queues & give them time to complete. * NB: *small* delay. User is expected to have a clue and to not run * heavy io in parallel with measurements. */ @@ -1422,10 +1416,14 @@ static void do_time(int cache /*,int fd*/) /* Now do the timing */ iterations = 0; /* Max time to run (small for cache, avoids getting - * huge total_MB which can overlow on print_timing) */ + * huge total_MB which can overlow unsigned type) */ elapsed2 = 510000; /* cache */ - if (!cache) + max_iterations = UINT_MAX; + if (!cache) { elapsed2 = 3000000; /* not cache */ + /* Don't want to read past the end! */ + max_iterations = dev_size_mb() / TIMING_BUF_MB; + } start = monotonic_us(); do { if (cache) @@ -1434,7 +1432,7 @@ static void do_time(int cache /*,int fd*/) elapsed = (unsigned)monotonic_us() - start; ++iterations; } while (elapsed < elapsed2 && iterations < max_iterations); - total_MB = (unsigned long)iterations * TIMING_BUF_MB; + total_MB = iterations * TIMING_BUF_MB; //printf(" elapsed:%u iterations:%u ", elapsed, iterations); if (cache) { /* Cache: remove lseek() and monotonic_us() overheads |