Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 May 2014 22:06:39 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r265472 - head/bin/dd
Message-ID:  <201405062206.s46M6dxW060155@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Tue May  6 22:06:39 2014
New Revision: 265472
URL: http://svnweb.freebsd.org/changeset/base/265472

Log:
  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

Modified:
  head/bin/dd/dd.c
  head/bin/dd/misc.c

Modified: head/bin/dd/dd.c
==============================================================================
--- head/bin/dd/dd.c	Tue May  6 22:04:50 2014	(r265471)
+++ head/bin/dd/dd.c	Tue May  6 22:06:39 2014	(r265472)
@@ -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

Modified: head/bin/dd/misc.c
==============================================================================
--- head/bin/dd/misc.c	Tue May  6 22:04:50 2014	(r265471)
+++ head/bin/dd/misc.c	Tue May  6 22:06:39 2014	(r265472)
@@ -40,14 +40,16 @@ static char sccsid[] = "@(#)misc.c	8.3 (
 __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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405062206.s46M6dxW060155>