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-w32-920c52a5c80969ab0c831e56cb26971e83942f0a.tar.gz
busybox-w32-920c52a5c80969ab0c831e56cb26971e83942f0a.tar.bz2
busybox-w32-920c52a5c80969ab0c831e56cb26971e83942f0a.zip
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)
1353 buf[i] &= 1; 1353 buf[i] &= 1;
1354} 1354}
1355 1355
1356static unsigned long long dev_size_mb(/*int fd*/ void) 1356static unsigned dev_size_mb(/*int fd*/ void)
1357{ 1357{
1358 union { 1358 union {
1359 unsigned long long blksize64; 1359 unsigned long long blksize64;
1360 unsigned blksize32; 1360 unsigned blksize32;
1361 } u; 1361 } u;
1362 1362
1363 if (0 == ioctl(fd, BLKGETSIZE64, &u.blksize64)) { // returns bytes 1363 if (0 == ioctl(fd, BLKGETSIZE64, &u.blksize64)) { // bytes
1364 return u.blksize64 / (1024 * 1024); 1364 u.blksize64 /= (1024 * 1024);
1365 } else {
1366 xioctl(fd, BLKGETSIZE, &u.blksize32); // sectors
1367 u.blksize64 = u.blksize32 / (2 * 1024);
1365 } 1368 }
1366 xioctl(fd, BLKGETSIZE, &u.blksize32); // returns sectors 1369 if (u.blksize64 > UINT_MAX)
1367 return u.blksize32 / (2 * 1024); 1370 return UINT_MAX;
1371 return u.blksize64;
1368} 1372}
1369 1373
1370static void print_timing(unsigned long m, unsigned elapsed_us) 1374static void print_timing(unsigned m, unsigned elapsed_us)
1371{ 1375{
1372 unsigned sec = elapsed_us / 1000000; 1376 unsigned sec = elapsed_us / 1000000;
1373 unsigned hs = (elapsed_us % 1000000) / 10000; 1377 unsigned hs = (elapsed_us % 1000000) / 10000;
1374 1378
1375 printf("%5lu MB in %u.%02u seconds = %lu kB/s\n", 1379 printf("%5u MB in %u.%02u seconds = %u kB/s\n",
1376 m, sec, hs, 1380 m, sec, hs,
1377 /* Trying to not overflow 32-bit arith in m * CONST 1381 /* + 1 prevents div-by-0 */
1378 * by keeping CONST not so big. But elapsed_us / CONST2 1382 (unsigned) ((unsigned long long)m * (1024 * 1000000) / (elapsed_us + 1))
1379 * also should not introduce big errors. Currently, 1383 // ~= (m * 1024) / (elapsed_us / 1000000)
1380 * 16000us is ~1.6% of 1 second.
1381 * "+ 1" prevents div-by-0. */
1382 (m * (1024 * 1000000 / (16*1024))) / (elapsed_us / (16*1024) + 1)
1383 // ~= (m * 1024 * 1000000) / elapsed_us
1384 // = (m * 1024) / (elapsed_us / 1000000)
1385 // = kb / elapsed_sec 1384 // = kb / elapsed_sec
1386 ); 1385 );
1387} 1386}
@@ -1392,19 +1391,14 @@ static void do_time(int cache /*,int fd*/)
1392 */ 1391 */
1393{ 1392{
1394 unsigned max_iterations, iterations; 1393 unsigned max_iterations, iterations;
1395 unsigned start; /* don't need to be long long */ 1394 unsigned start; /* doesn't need to be long long */
1396 unsigned elapsed, elapsed2; 1395 unsigned elapsed, elapsed2;
1397 unsigned long total_MB; 1396 unsigned total_MB;
1398 char *buf = xmalloc(TIMING_BUF_BYTES); 1397 char *buf = xmalloc(TIMING_BUF_BYTES);
1399 1398
1400 if (mlock(buf, TIMING_BUF_BYTES)) 1399 if (mlock(buf, TIMING_BUF_BYTES))
1401 bb_perror_msg_and_die("mlock"); 1400 bb_perror_msg_and_die("mlock");
1402 1401
1403 /* Don't want to read past the end! */
1404 max_iterations = UINT_MAX;
1405 if (!cache)
1406 max_iterations = dev_size_mb() / TIMING_BUF_MB;
1407
1408 /* Clear out the device request queues & give them time to complete. 1402 /* Clear out the device request queues & give them time to complete.
1409 * NB: *small* delay. User is expected to have a clue and to not run 1403 * NB: *small* delay. User is expected to have a clue and to not run
1410 * heavy io in parallel with measurements. */ 1404 * heavy io in parallel with measurements. */
@@ -1422,10 +1416,14 @@ static void do_time(int cache /*,int fd*/)
1422 /* Now do the timing */ 1416 /* Now do the timing */
1423 iterations = 0; 1417 iterations = 0;
1424 /* Max time to run (small for cache, avoids getting 1418 /* Max time to run (small for cache, avoids getting
1425 * huge total_MB which can overlow on print_timing) */ 1419 * huge total_MB which can overlow unsigned type) */
1426 elapsed2 = 510000; /* cache */ 1420 elapsed2 = 510000; /* cache */
1427 if (!cache) 1421 max_iterations = UINT_MAX;
1422 if (!cache) {
1428 elapsed2 = 3000000; /* not cache */ 1423 elapsed2 = 3000000; /* not cache */
1424 /* Don't want to read past the end! */
1425 max_iterations = dev_size_mb() / TIMING_BUF_MB;
1426 }
1429 start = monotonic_us(); 1427 start = monotonic_us();
1430 do { 1428 do {
1431 if (cache) 1429 if (cache)
@@ -1434,7 +1432,7 @@ static void do_time(int cache /*,int fd*/)
1434 elapsed = (unsigned)monotonic_us() - start; 1432 elapsed = (unsigned)monotonic_us() - start;
1435 ++iterations; 1433 ++iterations;
1436 } while (elapsed < elapsed2 && iterations < max_iterations); 1434 } while (elapsed < elapsed2 && iterations < max_iterations);
1437 total_MB = (unsigned long)iterations * TIMING_BUF_MB; 1435 total_MB = iterations * TIMING_BUF_MB;
1438 //printf(" elapsed:%u iterations:%u ", elapsed, iterations); 1436 //printf(" elapsed:%u iterations:%u ", elapsed, iterations);
1439 if (cache) { 1437 if (cache) {
1440 /* Cache: remove lseek() and monotonic_us() overheads 1438 /* Cache: remove lseek() and monotonic_us() overheads