From: Sami Kerola Date: Sun, 30 Jun 2013 18:11:22 +0000 (+0100) Subject: dmesg: make time stamps to be printed consistently X-Git-Tag: v2.24-rc1~465 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3c5384d05d3283cf93b5dbd8a4bb4fe245c4c19d;p=thirdparty%2Futil-linux.git dmesg: make time stamps to be printed consistently Earlier uptime determination, which was done with sysinfo(2), had one second resolution, which made time stamps to be rounded unstable way depending on when a dmesg command was executed. In practical terms; the command below was supposed not to differ but it did. $ diff -q <(dmesg --ctime) <(sleep 0.5 ; dmesg --ctime) [kzak@redhat.com: - add -lrt to Makemodule.am, - fallback to sysinfo() based boot time - use #ifdef] CC: Kay Sievers References: https://lkml.org/lkml/2013/6/30/37 Buglink: https://github.com/karelzak/util-linux/issues/24 Signed-off-by: Sami Kerola Signed-off-by: Karel Zak --- diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am index 977be5aff7..658b203c6c 100644 --- a/sys-utils/Makemodule.am +++ b/sys-utils/Makemodule.am @@ -55,7 +55,7 @@ if LINUX bin_PROGRAMS += dmesg dist_man_MANS += sys-utils/dmesg.1 dmesg_SOURCES = sys-utils/dmesg.c -dmesg_LDADD = $(LDADD) libcommon.la +dmesg_LDADD = $(LDADD) libcommon.la -lrt sbin_PROGRAMS += ctrlaltdel dist_man_MANS += sys-utils/ctrlaltdel.8 diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c index c098323c22..e6819308cf 100644 --- a/sys-utils/dmesg.c +++ b/sys-utils/dmesg.c @@ -145,7 +145,7 @@ struct dmesg_control { struct timeval lasttime; /* last printed timestamp */ struct tm lasttm; /* last localtime */ - time_t boot_time; /* system boot time */ + struct timeval boot_time; /* system boot time */ int action; /* SYSLOG_ACTION_* */ int method; /* DMESG_METHOD_* */ @@ -472,17 +472,30 @@ static int get_syslog_buffer_size(void) return n > 0 ? n : 0; } -static time_t get_boot_time(void) +static int get_boot_time(struct timeval *boot_time) { + struct timespec hires_uptime; + struct timeval lores_uptime, now; struct sysinfo info; - struct timeval tv; + if (gettimeofday(&now, NULL) != 0) { + warn(_("gettimeofday failed")); + return -errno; + } + +#ifdef CLOCK_BOOTTIME + if (clock_gettime(CLOCK_BOOTTIME, &hires_uptime) == 0) { + TIMESPEC_TO_TIMEVAL(&lores_uptime, &hires_uptime); + timersub(&now, &lores_uptime, boot_time); + return 0; + } +#endif + /* fallback */ if (sysinfo(&info) != 0) warn(_("sysinfo failed")); - else if (gettimeofday(&tv, NULL) != 0) - warn(_("gettimeofday failed")); - else - return tv.tv_sec -= info.uptime; + + boot_time->tv_sec = now.tv_sec - info.uptime; + boot_time->tv_usec = 0; return 0; } @@ -771,7 +784,7 @@ static struct tm *record_localtime(struct dmesg_control *ctl, struct dmesg_record *rec, struct tm *tm) { - time_t t = ctl->boot_time + rec->tv.tv_sec; + time_t t = ctl->boot_time.tv_sec + rec->tv.tv_sec; return localtime_r(&t, tm); } @@ -1339,8 +1352,7 @@ int main(int argc, char *argv[]) is_timefmt(&ctl, CTIME) || is_timefmt(&ctl, ISO8601)) { - ctl.boot_time = get_boot_time(); - if (!ctl.boot_time) + if (get_boot_time(&ctl.boot_time) != 0) ctl.time_fmt = DMESG_TIMEFTM_NONE; }