[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] Have xen dom0 still handle time of 1970
It's come to our attention, that the time gets screwed up when set between EPOCH and EPOCH + uptime. This may not seem important (because we don't live in the 70s anymore) but it makes LTP fail. LTP has a date test that checks what happens when set to EPOCH + 100 secs + 100 nsecs, and makes sure that it gets a proper result. The following patches helps xen handle the case where time is set back to Jan 1st 1970 (or anytime from EPOCH to EPOCH + uptime). Here's what you get without the patch: # date -u 010100011970 Thu Jan 1 00:01:00 UTC 1970 # date Mon Feb 22 16:42:30 EST 2010 Here's what you get with the patch: # date -u 010100011970 Thu Jan 1 00:01:00 UTC 1970 # date Wed Dec 31 19:01:01 EST 1969 -- Steve Signed-off-by: Steven Rostedt <srostedt@xxxxxxxxxx> diff -r fd2667419c53 linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Tue Jan 16 14:04:12 2007 -0500 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Wed Jan 17 10:34:06 2007 -0500 @@ -260,7 +260,8 @@ static void __update_wallclock(time_t se { long wtm_nsec, xtime_nsec; time_t wtm_sec, xtime_sec; - u64 tmp, wc_nsec; + s64 tmp, wc_nsec; + int s; /* Adjust wall-clock time base based on wall_jiffies ticks. */ wc_nsec = processed_system_time; @@ -270,8 +271,17 @@ static void __update_wallclock(time_t se /* Split wallclock base into seconds and nanoseconds. */ tmp = wc_nsec; + /* + * do_div does not like s64, and treats them as u64 + * and we will not get the expected result. + * So for those with time machines, let 1970 work + * again! + */ + s = tmp < 0 ? -1 : 1; + tmp *= s; xtime_nsec = do_div(tmp, 1000000000); xtime_sec = (time_t)tmp; + xtime_sec *= s; wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - xtime_sec); wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - xtime_nsec); @@ -289,7 +299,12 @@ static void update_wallclock(void) do { shadow_tv_version = s->wc_version; rmb(); - shadow_tv.tv_sec = s->wc_sec; + /* + * If someone decides to set the time to something + * before EPOCH + uptime, we can get a negative + * number here. + */ + shadow_tv.tv_sec = (s32)s->wc_sec; shadow_tv.tv_nsec = s->wc_nsec; rmb(); } while ((s->wc_version & 1) | (shadow_tv_version ^ s->wc_version)); diff -r fd2667419c53 xen/arch/x86/time.c --- a/xen/arch/x86/time.c Tue Jan 16 14:04:12 2007 -0500 +++ b/xen/arch/x86/time.c Wed Jan 17 10:34:06 2007 -0500 @@ -708,12 +708,23 @@ void update_domain_wallclock_time(struct /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */ void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base) { - u64 x; + s64 x; u32 y, _wc_sec, _wc_nsec; struct domain *d; + int s; x = (secs * 1000000000ULL) + (u64)nsecs - system_time_base; + s = x < 0 ? -1 : 1; + /* + * do_div does not like negative s64 numbers and treats them + * as u64, thus the result is unexpected if the s64 is + * negative. For those that still live in the 70s, and + * want their Xen boxes to do the same, we must handle the + * negative case. + */ + x *= s; y = do_div(x, 1000000000); + x *= s; spin_lock(&wc_lock); wc_sec = _wc_sec = (u32)x; _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |