summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorasomers <asomers@FreeBSD.org>2014-05-06 22:06:39 +0000
committerasomers <asomers@FreeBSD.org>2014-05-06 22:06:39 +0000
commitc9e9fdb2a1af4451fc0fff4e3bad8c43e47305c1 (patch)
treea78744ab8c4dbf1758a6ebb06f3b0f84ca6fd7a6 /bin
parentf10e28b41fb321b32c2b40e964d002b0cd1cc51a (diff)
downloadFreeBSD-src-c9e9fdb2a1af4451fc0fff4e3bad8c43e47305c1.zip
FreeBSD-src-c9e9fdb2a1af4451fc0fff4e3bad8c43e47305c1.tar.gz
dd(1) uses gettimeofday(2) to compute the throughput statistics. However,
gettimeofday returns the system clock, which may jump forward or back, especially if NTP is in use. If the time jumps backwards, then dd will see negative elapsed time, round it up to 1usec, and print an absurdly fast transfer rate. The solution is to use clock_gettime(2) with CLOCK_MONOTONIC_PRECISE as the clock_id. That clock advances steadily, regardless of changes to the system clock. Reviewed by: delphij MFC after: 3 days Sponsored by: Spectra Logic
Diffstat (limited to 'bin')
-rw-r--r--bin/dd/dd.c10
-rw-r--r--bin/dd/misc.c22
2 files changed, 20 insertions, 12 deletions
diff --git a/bin/dd/dd.c b/bin/dd/dd.c
index 7e5bd91..8048b6a 100644
--- a/bin/dd/dd.c
+++ b/bin/dd/dd.c
@@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/disklabel.h>
#include <sys/filio.h>
-#include <sys/time.h>
#include <ctype.h>
#include <err.h>
@@ -61,6 +60,8 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sysexits.h>
+#include <time.h>
#include <unistd.h>
#include "dd.h"
@@ -123,7 +124,7 @@ static void
setup(void)
{
u_int cnt;
- struct timeval tv;
+ struct timespec tv;
if (in.name == NULL) {
in.name = "stdin";
@@ -240,8 +241,9 @@ setup(void)
ctab = casetab;
}
- (void)gettimeofday(&tv, NULL);
- st.start = tv.tv_sec + tv.tv_usec * 1e-6;
+ if (clock_gettime(CLOCK_MONOTONIC_PRECISE, &tv))
+ err(EX_OSERR, "clock_gettime");
+ st.start = tv.tv_sec + tv.tv_nsec * 1.0e-9;
}
static void
diff --git a/bin/dd/misc.c b/bin/dd/misc.c
index 61f843b..0d8da70 100644
--- a/bin/dd/misc.c
+++ b/bin/dd/misc.c
@@ -40,14 +40,16 @@ static char sccsid[] = "@(#)misc.c 8.3 (Berkeley) 4/2/94";
__FBSDID("$FreeBSD$");
#include <sys/types.h>
-#include <sys/time.h>
+#include <err.h>
#include <errno.h>
#include <inttypes.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sysexits.h>
+#include <time.h>
#include <unistd.h>
#include "dd.h"
@@ -56,16 +58,20 @@ __FBSDID("$FreeBSD$");
void
summary(void)
{
- struct timeval tv;
- double secs;
+ struct timespec tv, tv_res;
+ double secs, res;
if (ddflags & C_NOINFO)
return;
- (void)gettimeofday(&tv, NULL);
- secs = tv.tv_sec + tv.tv_usec * 1e-6 - st.start;
- if (secs < 1e-6)
- secs = 1e-6;
+ if (clock_gettime(CLOCK_MONOTONIC_PRECISE, &tv))
+ err(EX_OSERR, "clock_gettime");
+ if (clock_getres(CLOCK_MONOTONIC_PRECISE, &tv_res))
+ err(EX_OSERR, "clock_getres");
+ secs = tv.tv_sec + tv.tv_nsec * 1.0e-9 - st.start;
+ res = tv_res.tv_sec + tv_res.tv_nsec * 1.0e-9;
+ if (secs < res)
+ secs = res;
(void)fprintf(stderr,
"%ju+%ju records in\n%ju+%ju records out\n",
st.in_full, st.in_part, st.out_full, st.out_part);
@@ -77,7 +83,7 @@ summary(void)
st.trunc, (st.trunc == 1) ? "block" : "blocks");
if (!(ddflags & C_NOXFER)) {
(void)fprintf(stderr,
- "%ju bytes transferred in %.6f secs (%.0f bytes/sec)\n",
+ "%ju bytes transferred in %.9f secs (%.0f bytes/sec)\n",
st.bytes, secs, st.bytes / secs);
}
need_summary = 0;
OpenPOWER on IntegriCloud