diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-09-28 13:38:08 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-09-28 13:38:08 +0000 |
commit | 920c52a5c80969ab0c831e56cb26971e83942f0a (patch) | |
tree | 5aa610db0c52265c4dac61d453990bf3b875d933 | |
parent | a0ad43b80b4a70a243b17ec464a194cf8369a940 (diff) | |
download | busybox-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.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) | |||
1353 | buf[i] &= 1; | 1353 | buf[i] &= 1; |
1354 | } | 1354 | } |
1355 | 1355 | ||
1356 | static unsigned long long dev_size_mb(/*int fd*/ void) | 1356 | static 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 | ||
1370 | static void print_timing(unsigned long m, unsigned elapsed_us) | 1374 | static 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 |