aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-09-28 13:38:08 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-09-28 13:38:08 +0000
commit920c52a5c80969ab0c831e56cb26971e83942f0a (patch)
tree5aa610db0c52265c4dac61d453990bf3b875d933
parenta0ad43b80b4a70a243b17ec464a194cf8369a940 (diff)
downloadbusybox-920c52a5c80969ab0c831e56cb26971e83942f0a.tar.gz
hdparm: more robust (re overflows) code. +38 bytes.
-rw-r--r--miscutils/hdparm.c48
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