]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
dmesg: make time stamps to be printed consistently
authorSami Kerola <kerolasa@iki.fi>
Sun, 30 Jun 2013 18:11:22 +0000 (19:11 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 1 Jul 2013 12:30:20 +0000 (14:30 +0200)
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 <kay@vrfy.org>
References: https://lkml.org/lkml/2013/6/30/37
Buglink: https://github.com/karelzak/util-linux/issues/24
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/Makemodule.am
sys-utils/dmesg.c

index 977be5aff73055cc99caab97cd51c772e8b0eb59..658b203c6cc18b11e3607fdf6eda88f56a3e7a62 100644 (file)
@@ -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
index c098323c22b58bd178ce20ed1cda68a5f8ba54d9..e6819308cf3fcd143c03259742dbb2229d356a04 100644 (file)
@@ -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;
        }