* [LTP] [PATCH] timers: add a new test case leapsec_timer
@ 2012-07-08 0:09 Lingzhu Xiang
2012-07-08 0:23 ` Lingzhu Xiang
2012-10-15 12:15 ` chrubis
0 siblings, 2 replies; 5+ messages in thread
From: Lingzhu Xiang @ 2012-07-08 0:09 UTC (permalink / raw)
To: LTP List
A bug in the hrtimer subsystem caused all TIMER_ABSTIME CLOCK_REALTIME
timers to expire one second early during and after leap seconds, thus
such sub-second timers expire immediately, causing load spikes if used
in fast loops. Calling clock_was_set() reverts this state. See [1].
[1]: http://lwn.net/Articles/504658/.
This patch is a regression test for the bug, based on the test case
provided by John Stultz from the above link, and also tries to recover
from inconsistency caused by reproduction of the bug.
Signed-off-by: Lingzhu Xiang <lxiang@redhat.com>
---
runtest/timers | 1 +
testcases/kernel/timers/leapsec/Makefile | 27 +++
testcases/kernel/timers/leapsec/leapsec_timer.c | 222 +++++++++++++++++++++++
3 files changed, 250 insertions(+), 0 deletions(-)
create mode 100644 testcases/kernel/timers/leapsec/Makefile
create mode 100644 testcases/kernel/timers/leapsec/leapsec_timer.c
diff --git a/runtest/timers b/runtest/timers
index 7a40125..a58ac57 100644
--- a/runtest/timers
+++ b/runtest/timers
@@ -10,3 +10,4 @@ timer_delete02 timer_delete02
timer_delete03 timer_delete03
timer_settime02 timer_settime02
timer_settime03 timer_settime03
+leapsec_timer leapsec_timer
diff --git a/testcases/kernel/timers/leapsec/Makefile b/testcases/kernel/timers/leapsec/Makefile
new file mode 100644
index 0000000..782cdbc
--- /dev/null
+++ b/testcases/kernel/timers/leapsec/Makefile
@@ -0,0 +1,27 @@
+#
+# Copyright (c) International Business Machines Corp., 2001
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+# the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+top_srcdir ?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+CPPFLAGS += -I$(abs_srcdir)/../include
+
+LDLIBS += -lrt
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/timers/leapsec/leapsec_timer.c b/testcases/kernel/timers/leapsec/leapsec_timer.c
new file mode 100644
index 0000000..2fa7bc8
--- /dev/null
+++ b/testcases/kernel/timers/leapsec/leapsec_timer.c
@@ -0,0 +1,222 @@
+/*
+ * Regression test for hrtimer early expiration during and after leap seconds
+ *
+ * A bug in the hrtimer subsystem caused all TIMER_ABSTIME CLOCK_REALTIME
+ * timers to expire one second early during leap second.
+ * See http://lwn.net/Articles/504658/.
+ *
+ * This is a regression test for the bug.
+ *
+ * Lingzhu Xiang <lxiang@redhat.com> Copyright (c) Red Hat, Inc., 2012.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include "test.h"
+#include "usctest.h"
+#include "common_timers.h"
+
+#define SECONDS_BEFORE_LEAP 2
+#define SECONDS_AFTER_LEAP 2
+
+char *TCID = "leapsec_timer";
+int TST_TOTAL = 1;
+
+static inline int in_order(struct timespec a, struct timespec b);
+static void adjtimex_status(struct timex *tx, int status);
+static const char *strtime(const struct timespec *now);
+static void test_hrtimer_early_expiration(void);
+static void run_leapsec(void);
+static void setup(void);
+static void cleanup(void);
+
+int main(int argc, char **argv)
+{
+ char *msg;
+ int lc;
+
+ msg = parse_opts(argc, argv, NULL, NULL);
+ if (msg != NULL)
+ tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
+
+ setup();
+
+ for (lc = 0; TEST_LOOPING(lc); lc++) {
+ Tst_count = 0;
+ run_leapsec();
+ }
+
+ cleanup();
+ tst_exit();
+}
+
+static inline int in_order(struct timespec a, struct timespec b)
+{
+ if (a.tv_sec < b.tv_sec)
+ return 1;
+ if (a.tv_sec > b.tv_sec)
+ return 0;
+ if (a.tv_nsec > b.tv_nsec)
+ return 0;
+ return 1;
+}
+
+static void adjtimex_status(struct timex *tx, int status)
+{
+ const char * const msgs[6] = {
+ "clock synchronized",
+ "insert leap second",
+ "delete leap second",
+ "leap second in progress",
+ "leap second has occurred",
+ "clock not synchronized",
+ };
+ int r;
+ struct timespec now;
+
+ tx->modes = ADJ_STATUS;
+ tx->status = status;
+ r = adjtimex(tx);
+ now.tv_sec = tx->time.tv_sec;
+ now.tv_nsec = tx->time.tv_usec * 1000;
+
+ if ((tx->status & status) != status)
+ tst_brkm(TBROK, cleanup, "adjtimex status %d not set", status);
+ else if (r < 0)
+ tst_brkm(TBROK | TERRNO, cleanup, "adjtimex");
+ else if (r < 6)
+ tst_resm(TINFO, "%s adjtimex: %s", strtime(&now), msgs[r]);
+ else
+ tst_resm(TINFO, "%s adjtimex: clock state %d",
+ strtime(&now), r);
+}
+
+static const char *strtime(const struct timespec *now)
+{
+ static char fmt[256], buf[256];
+
+ if (snprintf(fmt, sizeof(fmt), "%%F %%T.%09ld %%z", now->tv_nsec) < 0) {
+ buf[0] = '\0';
+ return buf;
+ }
+ if (!strftime(buf, sizeof(buf), fmt, localtime(&now->tv_sec))) {
+ buf[0] = '\0';
+ return buf;
+ }
+ return buf;
+}
+
+static void test_hrtimer_early_expiration(void)
+{
+ struct timespec now, target;
+ int r, fail;
+
+ clock_gettime(CLOCK_REALTIME, &now);
+ tst_resm(TINFO, "now is %s", strtime(&now));
+
+ target = now;
+ target.tv_sec++;
+ tst_resm(TINFO, "sleep till %s", strtime(&target));
+ r = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &target, NULL);
+ if (r < 0) {
+ tst_resm(TINFO | TERRNO, "clock_nanosleep");
+ return;
+ }
+
+ clock_gettime(CLOCK_REALTIME, &now);
+ tst_resm(TINFO, "now is %s", strtime(&now));
+
+ fail = !in_order(target, now);
+ tst_resm(fail ? TFAIL : TINFO, "hrtimer early expiration is %s.",
+ fail ? "detected" : "not detected");
+}
+
+static void run_leapsec(void)
+{
+ const struct timespec sleeptime = {0, NSEC_PER_SEC / 2};
+ struct timespec now, leap, start;
+ struct timex tx;
+
+ clock_gettime(CLOCK_REALTIME, &now);
+ start = now;
+ tst_resm(TINFO, "test start at %s", strtime(&now));
+
+ test_hrtimer_early_expiration();
+
+ /* calculate the next leap second */
+ now.tv_sec += 86400 - now.tv_sec % 86400;
+ now.tv_nsec = 0;
+ leap = now;
+ tst_resm(TINFO, "scheduling leap second %s", strtime(&leap));
+
+ /* start before the leap second */
+ now.tv_sec -= SECONDS_BEFORE_LEAP;
+ if (clock_settime(CLOCK_REALTIME, &now) < 0)
+ tst_brkm(TBROK | TERRNO, cleanup, "clock_settime");
+ tst_resm(TINFO, "setting time to %s", strtime(&now));
+
+ /* reset NTP time state */
+ adjtimex_status(&tx, STA_PLL);
+ adjtimex_status(&tx, 0);
+
+ /* set the leap second insert flag */
+ adjtimex_status(&tx, STA_INS);
+
+ /* reliably sleep till after the leap second */
+ while (tx.time.tv_sec < leap.tv_sec + SECONDS_AFTER_LEAP) {
+ adjtimex_status(&tx, tx.status);
+ clock_nanosleep(CLOCK_MONOTONIC, 0, &sleeptime, NULL);
+ }
+
+ test_hrtimer_early_expiration();
+
+ adjtimex_status(&tx, STA_PLL);
+ adjtimex_status(&tx, 0);
+
+ /* recover from timer expiring state and restore time */
+ clock_gettime(CLOCK_REALTIME, &now);
+ start.tv_sec += now.tv_sec - (leap.tv_sec - SECONDS_BEFORE_LEAP);
+ start.tv_nsec += now.tv_nsec;
+ start.tv_sec += start.tv_nsec / NSEC_PER_SEC;
+ start.tv_nsec = start.tv_nsec % NSEC_PER_SEC;
+ tst_resm(TINFO, "restoring time to %s", strtime(&start));
+ /* calls clock_was_set() in kernel to revert inconsistency */
+ if (clock_settime(CLOCK_REALTIME, &start) < 0)
+ tst_brkm(TBROK | TERRNO, cleanup, "clock_settime");
+
+ test_hrtimer_early_expiration();
+}
+
+static void setup(void)
+{
+ tst_require_root(NULL);
+ tst_sig(NOFORK, DEF_HANDLER, CLEANUP);
+ TEST_PAUSE;
+}
+
+static void cleanup(void)
+{
+ struct timespec now;
+ clock_gettime(CLOCK_REALTIME, &now);
+ /* Calls clock_was_set() in kernel to revert inconsistency.
+ * The only possible EPERM doesn't matter here. */
+ clock_settime(CLOCK_REALTIME, &now);
+ TEST_CLEANUP;
+}
--
1.7.7.6
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [LTP] [PATCH] timers: add a new test case leapsec_timer
2012-07-08 0:09 [LTP] [PATCH] timers: add a new test case leapsec_timer Lingzhu Xiang
@ 2012-07-08 0:23 ` Lingzhu Xiang
2012-07-06 10:00 ` Caspar Zhang
2012-10-15 12:15 ` chrubis
1 sibling, 1 reply; 5+ messages in thread
From: Lingzhu Xiang @ 2012-07-08 0:23 UTC (permalink / raw)
To: LTP List
On 07/08/2012 08:09 AM, Lingzhu Xiang wrote:
> A bug in the hrtimer subsystem caused all TIMER_ABSTIME CLOCK_REALTIME
> timers to expire one second early during and after leap seconds, thus
> such sub-second timers expire immediately, causing load spikes if used
> in fast loops. Calling clock_was_set() reverts this state. See [1].
>
> [1]: http://lwn.net/Articles/504658/.
>
> This patch is a regression test for the bug, based on the test case
> provided by John Stultz from the above link, and also tries to recover
> from inconsistency caused by reproduction of the bug.
A sample test run looks like this:
leapsec_timer 0 TINFO : test start at 2012-07-08
08:02:32.996771295 +0800
leapsec_timer 0 TINFO : now is 2012-07-08 08:02:32.996929883 +0800
leapsec_timer 0 TINFO : sleep till 2012-07-08 08:02:33.996929883 +0800
leapsec_timer 0 TINFO : now is 2012-07-08 08:02:33.996975957 +0800
leapsec_timer 0 TINFO : hrtimer early expiration is not detected.
leapsec_timer 0 TINFO : scheduling leap second 2012-07-09
08:00:00.000000000 +0800
leapsec_timer 0 TINFO : setting time to 2012-07-09
07:59:58.000000000 +0800
leapsec_timer 0 TINFO : 2012-07-09 07:59:58.000080000 +0800
adjtimex: clock synchronized
leapsec_timer 0 TINFO : 2012-07-09 07:59:58.000101000 +0800
adjtimex: clock synchronized
leapsec_timer 0 TINFO : 2012-07-09 07:59:58.000119000 +0800
adjtimex: insert leap second
leapsec_timer 0 TINFO : 2012-07-09 07:59:58.000138000 +0800
adjtimex: insert leap second
leapsec_timer 0 TINFO : 2012-07-09 07:59:58.500174000 +0800
adjtimex: insert leap second
leapsec_timer 0 TINFO : 2012-07-09 07:59:59.000246000 +0800
adjtimex: insert leap second
leapsec_timer 0 TINFO : 2012-07-09 07:59:59.500320000 +0800
adjtimex: insert leap second
leapsec_timer 0 TINFO : 2012-07-09 07:59:59.000368000 +0800
adjtimex: leap second in progress
leapsec_timer 0 TINFO : 2012-07-09 07:59:59.500403000 +0800
adjtimex: leap second in progress
leapsec_timer 0 TINFO : 2012-07-09 08:00:00.000432000 +0800
adjtimex: leap second has occurred
leapsec_timer 0 TINFO : 2012-07-09 08:00:00.500457000 +0800
adjtimex: leap second has occurred
leapsec_timer 0 TINFO : 2012-07-09 08:00:01.000475000 +0800
adjtimex: leap second has occurred
leapsec_timer 0 TINFO : 2012-07-09 08:00:01.500489000 +0800
adjtimex: leap second has occurred
leapsec_timer 0 TINFO : 2012-07-09 08:00:02.000506000 +0800
adjtimex: leap second has occurred
leapsec_timer 0 TINFO : now is 2012-07-09 08:00:02.500524432 +0800
leapsec_timer 0 TINFO : sleep till 2012-07-09 08:00:03.500524432 +0800
leapsec_timer 0 TINFO : now is 2012-07-09 08:00:02.500550236 +0800
leapsec_timer 1 TFAIL : hrtimer early expiration is detected.
leapsec_timer 0 TINFO : 2012-07-09 08:00:02.500561000 +0800
adjtimex: clock synchronized
leapsec_timer 0 TINFO : 2012-07-09 08:00:02.500568000 +0800
adjtimex: clock synchronized
leapsec_timer 0 TINFO : restoring time to 2012-07-08
08:02:37.497346606 +0800
leapsec_timer 0 TINFO : now is 2012-07-08 08:02:37.497351161 +0800
leapsec_timer 0 TINFO : sleep till 2012-07-08 08:02:38.497351161 +0800
leapsec_timer 0 TINFO : now is 2012-07-08 08:02:38.497391392 +0800
leapsec_timer 0 TINFO : hrtimer early expiration is not detected.
As can be observed, the first timer before the leap second and third timer
after resetting time state worked as expected (early expiration not
detected),
but the second timer after the leap second before resetting time state
returned unexpectedly early. Thus the above bug was reproduced.
Note that this test case might cause kernel freeze. Running with -c 5 will
highly increase the likelihood of that.
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [LTP] [PATCH] timers: add a new test case leapsec_timer
2012-07-08 0:23 ` Lingzhu Xiang
@ 2012-07-06 10:00 ` Caspar Zhang
2012-07-09 2:24 ` Lingzhu Xiang
0 siblings, 1 reply; 5+ messages in thread
From: Caspar Zhang @ 2012-07-06 10:00 UTC (permalink / raw)
To: Lingzhu Xiang; +Cc: LTP List
On 07/08/2012 08:23 AM, Lingzhu Xiang wrote:
> Note that this test case might cause kernel freeze. Running with -c 5 will
> highly increase the likelihood of that.
IIRC, -c is broken, is `-i 5` able to freeze the kernel? If yes, it
would be better to add a new entry to $LTPROOT/runtest/timers or update
the original entry w/ `-i 5` option.
Caspar
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [LTP] [PATCH] timers: add a new test case leapsec_timer
2012-07-06 10:00 ` Caspar Zhang
@ 2012-07-09 2:24 ` Lingzhu Xiang
0 siblings, 0 replies; 5+ messages in thread
From: Lingzhu Xiang @ 2012-07-09 2:24 UTC (permalink / raw)
To: Caspar Zhang; +Cc: LTP List
On 07/06/2012 06:00 PM, Caspar Zhang wrote:
> On 07/08/2012 08:23 AM, Lingzhu Xiang wrote:
>> Note that this test case might cause kernel freeze. Running with -c 5 will
>> highly increase the likelihood of that.
>
> IIRC, -c is broken, is `-i 5` able to freeze the kernel? If yes, it
> would be better to add a new entry to $LTPROOT/runtest/timers or update
> the original entry w/ `-i 5` option.
Nope. It seems the hard hang caused by concurrent leap second is unresolved
in upstream "NOTE: Some reports have been of a hard hang right at or before
the leapsecond. I've not been able to reproduce or diagnose this..." [1]
[1]: https://lkml.org/lkml/2012/7/4/78
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [LTP] [PATCH] timers: add a new test case leapsec_timer
2012-07-08 0:09 [LTP] [PATCH] timers: add a new test case leapsec_timer Lingzhu Xiang
2012-07-08 0:23 ` Lingzhu Xiang
@ 2012-10-15 12:15 ` chrubis
1 sibling, 0 replies; 5+ messages in thread
From: chrubis @ 2012-10-15 12:15 UTC (permalink / raw)
To: Lingzhu Xiang; +Cc: LTP List
Hi!
Commited, thanks.
--
Cyril Hrubis
chrubis@suse.cz
------------------------------------------------------------------------------
Don't let slow site performance ruin your business. Deploy New Relic APM
Deploy New Relic app performance management and know exactly
what is happening inside your Ruby, Python, PHP, Java, and .NET app
Try New Relic at no cost today and get our sweet Data Nerd shirt too!
http://p.sf.net/sfu/newrelic-dev2dev
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-10-15 12:17 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-08 0:09 [LTP] [PATCH] timers: add a new test case leapsec_timer Lingzhu Xiang
2012-07-08 0:23 ` Lingzhu Xiang
2012-07-06 10:00 ` Caspar Zhang
2012-07-09 2:24 ` Lingzhu Xiang
2012-10-15 12:15 ` chrubis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox