From owner-svn-src-all@FreeBSD.ORG Tue May 6 22:06:39 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id D212AC9B; Tue, 6 May 2014 22:06:39 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id BF7E9AC4; Tue, 6 May 2014 22:06:39 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s46M6d11060157; Tue, 6 May 2014 22:06:39 GMT (envelope-from asomers@svn.freebsd.org) Received: (from asomers@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s46M6dxW060155; Tue, 6 May 2014 22:06:39 GMT (envelope-from asomers@svn.freebsd.org) Message-Id: <201405062206.s46M6dxW060155@svn.freebsd.org> From: Alan Somers Date: Tue, 6 May 2014 22:06:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r265472 - head/bin/dd X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 06 May 2014 22:06:40 -0000 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 #include #include -#include #include #include @@ -61,6 +60,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #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 -#include +#include #include #include #include #include #include #include +#include +#include #include #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;