diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c index c540ff93c..0a689d87e 100644 --- a/miscutils/hdparm.c +++ b/miscutils/hdparm.c @@ -393,26 +393,26 @@ void identify_from_stdin(void); */ /* words 89, 90, SECU ERASE TIME */ -#define ERASE_BITS 0x00ff +#define ERASE_BITS 0x00ff /* word 92: master password revision */ /* NOVAL_0 or NOVAL_1 means no support for master password revision */ /* word 93: hw reset result */ -#define CBLID 0x2000 /* CBLID status */ -#define RST0 0x0001 /* 1=reset to device #0 */ -#define DEV_DET 0x0006 /* how device num determined */ -#define JUMPER_VAL 0x0002 /* device num determined by jumper */ -#define CSEL_VAL 0x0004 /* device num determined by CSEL_VAL */ +#define CBLID 0x2000 /* CBLID status */ +#define RST0 0x0001 /* 1=reset to device #0 */ +#define DEV_DET 0x0006 /* how device num determined */ +#define JUMPER_VAL 0x0002 /* device num determined by jumper */ +#define CSEL_VAL 0x0004 /* device num determined by CSEL_VAL */ /* word 127: removable media status notification feature set support */ -#define RM_STAT_BITS 0x0003 -#define RM_STAT_SUP 0x0001 +#define RM_STAT_BITS 0x0003 +#define RM_STAT_SUP 0x0001 /* word 128: security */ -#define SECU_ENABLED 0x0002 -#define SECU_LEVEL 0x0010 -#define NUM_SECU_STR 6 +#define SECU_ENABLED 0x0002 +#define SECU_LEVEL 0x0010 +#define NUM_SECU_STR 6 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY static const char * const secu_str[] = { "supported", /* word 128, bit 0 */ @@ -425,22 +425,21 @@ static const char * const secu_str[] = { #endif /* word 160: CFA power mode */ -#define VALID_W160 0x8000 /* 1=word valid */ -#define PWR_MODE_REQ 0x2000 /* 1=CFA power mode req'd by some cmds*/ -#define PWR_MODE_OFF 0x1000 /* 1=CFA power moded disabled */ -#define MAX_AMPS 0x0fff /* value = max current in ma */ +#define VALID_W160 0x8000 /* 1=word valid */ +#define PWR_MODE_REQ 0x2000 /* 1=CFA power mode req'd by some cmds*/ +#define PWR_MODE_OFF 0x1000 /* 1=CFA power moded disabled */ +#define MAX_AMPS 0x0fff /* value = max current in ma */ /* word 255: integrity */ -#define SIG 0x00ff /* signature location */ -#define SIG_VAL 0x00A5 /* signature value */ +#define SIG 0x00ff /* signature location */ +#define SIG_VAL 0x00a5 /* signature value */ -#define TIMING_MB 64 -#define TIMING_BUF_MB 1 -#define TIMING_BUF_BYTES (TIMING_BUF_MB * 1024 * 1024) -#define TIMING_BUF_COUNT (timing_MB / TIMING_BUF_MB) -#define BUFCACHE_FACTOR 2 +#define TIMING_MB 64 +#define TIMING_BUF_MB 1 +#define TIMING_BUF_BYTES (TIMING_BUF_MB * 1024 * 1024) +#define BUFCACHE_FACTOR 2 -#undef DO_FLUSHCACHE /* under construction: force cache flush on -W0 */ +#undef DO_FLUSHCACHE /* under construction: force cache flush on -W0 */ /* Busybox messages and functions */ static int bb_ioctl(int fd, int request, void *argp, const char *string) @@ -775,7 +774,7 @@ static void identify(uint16_t *id_supplied) bbbig = (uint64_t)val[LBA_64_MSB] << 48 | (uint64_t)val[LBA_48_MSB] << 32 | (uint64_t)val[LBA_MID] << 16 | - val[LBA_LSB] ; + val[LBA_LSB]; printf("\tLBA48 user addressable sectors:%11"PRIu64"\n", bbbig); } @@ -916,7 +915,7 @@ static void identify(uint16_t *id_supplied) * than n (e.g. 3, 2, 1 and 0). Print all the modes. */ if ((val[WHATS_VALID] & OK_W64_70) && (val[ADV_PIO_MODES] & PIO_SUP)) { jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007; - for (ii = 0; ii <= PIO_MODE_MAX ; ii++) { + for (ii = 0; ii <= PIO_MODE_MAX; ii++) { if (jj & 0x0001) printf("pio%d ", ii); jj >>=1; } @@ -1246,7 +1245,7 @@ static void dump_identity(const struct hd_driveid *id) static void flush_buffer_cache(int fd) { fsync(fd); /* flush buffers */ - bb_ioctl(fd, BLKFLSBUF, NULL, "BLKFLSBUF") ;/* do it again, big time */ + bb_ioctl(fd, BLKFLSBUF, NULL, "BLKFLSBUF"); /* do it again, big time */ #ifdef HDIO_DRIVE_CMD sleep(1); if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) /* await completion */ @@ -1276,14 +1275,6 @@ static int read_big_block(int fd, char *buf) return 0; } -static void print_timing(int t, double e) -{ - if (t >= e) /* more than 1MB/s */ - printf("%2d MB in %5.2f seconds =%6.2f %cB/sec\n", t, e, t / e, 'M'); - else - printf("%2d MB in %5.2f seconds =%6.2f %cB/sec\n", t, e, t / e * 1024, 'k'); -} - static int do_blkgetsize(int fd, unsigned long long *blksize64) { int rc; @@ -1300,17 +1291,22 @@ static int do_blkgetsize(int fd, unsigned long long *blksize64) return rc; } +static void print_timing(unsigned t, double e) +{ + if (t >= e) /* more than 1MB/s */ + printf("%4d MB in %.2f seconds = %.2f %cB/sec\n", t, e, t / e, 'M'); + else + printf("%4d MB in %.2f seconds = %.2f %cB/sec\n", t, e, t / e * 1024, 'k'); +} + static void do_time(int flag, int fd) -/* - flag = 0 time_cache - flag = 1 time_device -*/ +/* flag = 0 time_cache, 1 time_device */ { static const struct itimerval thousand = {{1000, 0}, {1000, 0}}; - struct itimerval e1, e2; - double elapsed, elapsed2; - unsigned max_iterations = 1024, total_MB, iterations; + struct itimerval itv; + unsigned elapsed, elapsed2; + unsigned max_iterations, total_MB, iterations; unsigned long long blksize; RESERVE_CONFIG_BUFFER(buf, TIMING_BUF_BYTES); @@ -1319,78 +1315,60 @@ static void do_time(int flag, int fd) goto quit2; } + max_iterations = 1024; if (0 == do_blkgetsize(fd, &blksize)) { max_iterations = blksize / (2 * 1024) / TIMING_BUF_MB; } /* Clear out the device request queues & give them time to complete */ sync(); - sleep(3); - + sleep(2); + if (flag == 0) { /* Time cache */ + if (seek_to_zero(fd)) + goto quit; + if (read_big_block(fd, buf)) + goto quit; + printf(" Timing buffer-cache reads: "); + } else { /* Time device */ + printf(" Timing buffered disk reads: "); + } + fflush(stdout); + iterations = 0; + /* + * getitimer() is used rather than gettimeofday() because + * it is much more consistent (on my machine, at least). + */ setitimer(ITIMER_REAL, &thousand, NULL); - - if (flag == 0) { - /* Time cache */ - - if (seek_to_zero(fd)) return; - if (read_big_block(fd, buf)) return; - printf(" Timing cached reads: "); - fflush(stdout); - - /* Now do the timing */ - iterations = 0; - getitimer(ITIMER_REAL, &e1); - do { - ++iterations; - if (seek_to_zero(fd) || read_big_block(fd, buf)) - goto quit; - getitimer(ITIMER_REAL, &e2); - elapsed = (e1.it_value.tv_sec - e2.it_value.tv_sec) - + ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0); - } while (elapsed < 2.0); - total_MB = iterations * TIMING_BUF_MB; - + /* Now do the timing */ + do { + ++iterations; + if ((flag == 0) && seek_to_zero(fd)) + goto quit; + if (read_big_block(fd, buf)) + goto quit; + getitimer(ITIMER_REAL, &itv); + elapsed = (1000 - itv.it_value.tv_sec) * 1000000 + - itv.it_value.tv_usec; + } while (elapsed < 3000000 && iterations < max_iterations); + total_MB = iterations * TIMING_BUF_MB; + if (flag == 0) { /* Now remove the lseek() and getitimer() overheads from the elapsed time */ - getitimer(ITIMER_REAL, &e1); + setitimer(ITIMER_REAL, &thousand, NULL); do { if (seek_to_zero(fd)) goto quit; - getitimer(ITIMER_REAL, &e2); - elapsed2 = (e1.it_value.tv_sec - e2.it_value.tv_sec) - + ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0); + getitimer(ITIMER_REAL, &itv); + elapsed2 = (1000 - itv.it_value.tv_sec) * 1000000 + - itv.it_value.tv_usec; } while (--iterations); - elapsed -= elapsed2; - print_timing(BUFCACHE_FACTOR * total_MB, elapsed); + total_MB *= BUFCACHE_FACTOR; flush_buffer_cache(fd); - sleep(1); - } else { - /* Time device */ - - printf(" Timing buffered disk reads: "); - fflush(stdout); - /* - * getitimer() is used rather than gettimeofday() because - * it is much more consistent (on my machine, at least). - */ - /* Now do the timings for real */ - iterations = 0; - getitimer(ITIMER_REAL, &e1); - do { - ++iterations; - if (read_big_block(fd, buf)) - goto quit; - getitimer(ITIMER_REAL, &e2); - elapsed = (e1.it_value.tv_sec - e2.it_value.tv_sec) - + ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0); - } while (elapsed < 3.0 && iterations < max_iterations); - - total_MB = iterations * TIMING_BUF_MB; - print_timing(total_MB, elapsed); } -quit: + print_timing(total_MB, elapsed / 1000000.0); + quit: munlock(buf, TIMING_BUF_BYTES); -quit2: + quit2: RELEASE_CONFIG_BUFFER(buf); }