The kernel uses 32-bit signed value(time_t) for seconds since
1970-01-01:00:00:00, so it will overflow at 2038-01-19 03:14:08 on
32-bit systems. We call this "2038 safety" issue.
Currently, I'm working with "John Stultz" to deal with this issue.
This series doesn't involve any functional change, and mainly converts
do_settimeofday() to use timespec64(By adding new do_settimeofday64()
using timespec64). During the conversion, it needs to handle mktime(),
rtc_tm_to_time(), rtc_time_to_tm() and other functions similarly due
to dependencies.
The main processing logic here is:
Add xxx64() safe version:
*Add do_settimeofday64() safe version(using timespec64)
*Add mktime64() safe version(using time64_t)
*Add rtc_tm_to_time64() safe version(using time64_t)
*Add rtc_time_to_tm64() safe version(using time64_t)
Clean unsafe do_settimeofday():
*Convert all users of do_settimeofday() to use do_settimeofday64()
*Remove do_settimeofday()
*Try the best to eliminate TODOs brought by these patches
Clean unsafe mktime()/rtc_tm_to_time()/rtc_time_to_tm() respectively:
*Convert all users of xxx() to use xxx64() one by one
*Try the best to eliminate TODOs brought by these patches
*Remove xxx()
So the rest of this patch series does tons of work on these conversions.
NOTE: This series actually contains 153 patches in total, but just sent
out a small subset here for feedback to make sure there are no objections
with my approach.
Please access the link below for all the related patches if interested:
https://git.linaro.org/people/pang.xunlei/linuxstable.git
pang.xunlei (11):
time: Add do_settimeofday64() safe version(using timespec64)
time: Add mktime64() safe version(using time64_t)
time: Add rtc_tm_to_time64() safe version(using time64_t)
time: Add rtc_time_to_tm64() safe version(using time64_t)
time: Convert all users of do_settimeofday() to use
do_settimeofday64()
time: Remove do_settimeofday()
time: Convert alarm_set_rtc() to use timespec64
time: Convert xen_read_wallclock() to use timespec64
time: Convert pvclock_read_wallclock() to use timespec64
time: Convert x86_platform.set_wallclock()to use timespec64
time: Convert x86_platform.get_wallclock()to use timespec64
arch/x86/include/asm/intel_mid_vrtc.h | 4 +-
arch/x86/include/asm/mc146818rtc.h | 4 +-
arch/x86/include/asm/pvclock.h | 2 +-
arch/x86/include/asm/x86_init.h | 11 ++++--
arch/x86/kernel/kvmclock.c | 6 +--
arch/x86/kernel/pvclock.c | 9 +++--
arch/x86/kernel/rtc.c | 30 ++++++++++-----
arch/x86/lguest/boot.c | 4 +-
arch/x86/platform/intel-mid/intel_mid_vrtc.c | 12 +++---
arch/x86/xen/time.c | 13 +++----
drivers/hv/hv_util.c | 6 +--
drivers/rtc/hctosys.c | 10 ++---
drivers/rtc/rtc-lib.c | 35 ++++++++++++++---
drivers/staging/android/alarm-dev.c | 14 +++++--
include/linux/lguest.h | 2 +-
include/linux/rtc.h | 2 +
include/linux/time.h | 4 ++
include/linux/time64.h | 5 ++-
include/linux/timekeeping.h | 2 +-
kernel/compat.c | 5 ++-
kernel/time/time.c | 52 ++++++++++++++++++++++++--
kernel/time/timekeeping.c | 20 +++++-----
22 files changed, 176 insertions(+), 76 deletions(-)
--
1.7.9.5
The kernel uses 32-bit signed value(time_t) for seconds elapsed
1970-01-01:00:00:00, thus it will overflow at 2038-01-19 03:14:08
on 32-bit systems. We call this "2038 safety" issue.
As part of addressing 2038 saftey for in-kernel uses, this patch
adds safe do_settimeofday64() using timespec64. After this patch,
do_settimeofday() should be replaced by do_settimeofday64() one
by one. Eventually, do_settimeofday() will be removed from the
kernel when it has no users.
Signed-off-by: pang.xunlei <[email protected]>
---
include/linux/timekeeping.h | 1 +
kernel/time/timekeeping.c | 34 +++++++++++++++++++++++++---------
2 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h
index 1caa6b0..afc61c3 100644
--- a/include/linux/timekeeping.h
+++ b/include/linux/timekeeping.h
@@ -10,6 +10,7 @@ extern int timekeeping_suspended;
* Get and set timeofday
*/
extern void do_gettimeofday(struct timeval *tv);
+extern int do_settimeofday64(const struct timespec64 *ts);
extern int do_settimeofday(const struct timespec *tv);
extern int do_sys_settimeofday(const struct timespec *tv,
const struct timezone *tz);
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index ec1791f..f0dcbc0 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -703,18 +703,19 @@ void do_gettimeofday(struct timeval *tv)
EXPORT_SYMBOL(do_gettimeofday);
/**
- * do_settimeofday - Sets the time of day
- * @tv: pointer to the timespec variable containing the new time
+ * do_settimeofday64 - Sets the time of day
+ * @ts: pointer to the timespec64 variable containing the new time
*
* Sets the time of day to the new time and update NTP and notify hrtimers
+ * Safe version for 2038 safety.
*/
-int do_settimeofday(const struct timespec *tv)
+int do_settimeofday64(const struct timespec64 *ts)
{
struct timekeeper *tk = &tk_core.timekeeper;
- struct timespec64 ts_delta, xt, tmp;
+ struct timespec64 ts_delta, xt;
unsigned long flags;
- if (!timespec_valid_strict(tv))
+ if (!timespec64_valid_strict(ts))
return -EINVAL;
raw_spin_lock_irqsave(&timekeeper_lock, flags);
@@ -723,13 +724,12 @@ int do_settimeofday(const struct timespec *tv)
timekeeping_forward_now(tk);
xt = tk_xtime(tk);
- ts_delta.tv_sec = tv->tv_sec - xt.tv_sec;
- ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec;
+ ts_delta.tv_sec = ts->tv_sec - xt.tv_sec;
+ ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec;
tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta));
- tmp = timespec_to_timespec64(*tv);
- tk_set_xtime(tk, &tmp);
+ tk_set_xtime(tk, ts);
timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
@@ -741,6 +741,22 @@ int do_settimeofday(const struct timespec *tv)
return 0;
}
+EXPORT_SYMBOL(do_settimeofday64);
+
+/**
+ * do_settimeofday - Sets the time of day
+ * @tv: pointer to the timespec variable containing the new time
+ *
+ * Sets the time of day to the new time and update NTP and notify hrtimers
+ * TODO: [2038 safety] should be replaced by do_settimeofday64().
+ */
+int do_settimeofday(const struct timespec *tv)
+{
+ struct timespec64 ts64;
+
+ ts64 = timespec_to_timespec64(*tv);
+ return do_settimeofday64(&ts64);
+}
EXPORT_SYMBOL(do_settimeofday);
/**
--
1.7.9.5
As part of addressing 2038 saftey for in-kernel uses, this patch
adds safe mktime64() using time64_t. After this patch, mktime()
should be replaced by mktime64() one by one. Eventually, mktime()
will be removed from the kernel when it has no users.
Signed-off-by: pang.xunlei <[email protected]>
---
include/linux/time.h | 4 ++++
kernel/time/time.c | 39 +++++++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+)
diff --git a/include/linux/time.h b/include/linux/time.h
index 8c42cf8..5c2c077 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -39,6 +39,10 @@ static inline int timeval_compare(const struct timeval *lhs, const struct timeva
return lhs->tv_usec - rhs->tv_usec;
}
+extern time64_t mktime64(const unsigned int year, const unsigned int mon,
+ const unsigned int day, const unsigned int hour,
+ const unsigned int min, const unsigned int sec);
+
extern unsigned long mktime(const unsigned int year, const unsigned int mon,
const unsigned int day, const unsigned int hour,
const unsigned int min, const unsigned int sec);
diff --git a/kernel/time/time.c b/kernel/time/time.c
index a9ae20f..f44efdb 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -304,6 +304,44 @@ struct timespec timespec_trunc(struct timespec t, unsigned gran)
}
EXPORT_SYMBOL(timespec_trunc);
+/*
+ * Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year/100+year/400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * Safe version 2038 safety on 32-bit systems.
+ */
+time64_t
+mktime64(const unsigned int year0, const unsigned int mon0,
+ const unsigned int day, const unsigned int hour,
+ const unsigned int min, const unsigned int sec)
+{
+ time64_t ret;
+ unsigned int mon = mon0, year = year0;
+
+ /* 1..12 -> 11,12,1..10 */
+ if (0 >= (int) (mon -= 2)) {
+ mon += 12; /* Puts Feb last since it has leap day */
+ year -= 1;
+ }
+
+ ret = (year/4 - year/100 + year/400 + 367*mon/12 + day) + year*365 - 719499;
+ ret = ret*24 + hour; /* now have hours */
+ ret = ret*60 + min; /* now have minutes */
+ ret = ret*60 + sec; /* finally seconds */
+
+ return ret;
+}
+
+EXPORT_SYMBOL(mktime64);
+
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
* => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
@@ -318,6 +356,7 @@ EXPORT_SYMBOL(timespec_trunc);
* WARNING: this function will overflow on 2106-02-07 06:28:16 on
* machines where long is 32-bit! (However, as time_t is signed, we
* will already get problems at other places on 2038-01-19 03:14:08)
+ * TODO: [2038 safety] should be replaced by mktime64().
*/
unsigned long
mktime(const unsigned int year0, const unsigned int mon0,
--
1.7.9.5
As part of addressing 2038 saftey for in-kernel uses, this patch
adds safe rtc_tm_to_time64() using time64_t. After this patch,
rtc_tm_to_time() should be replaced by rtc_tm_to_time64() one by
one. Eventually, rtc_tm_to_time() will be removed from the kernel
when it has no users.
Signed-off-by: pang.xunlei <[email protected]>
---
drivers/rtc/rtc-lib.c | 15 ++++++++++++++-
include/linux/rtc.h | 1 +
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
index c4cf057..6948cbd 100644
--- a/drivers/rtc/rtc-lib.c
+++ b/drivers/rtc/rtc-lib.c
@@ -110,10 +110,23 @@ EXPORT_SYMBOL(rtc_valid_tm);
/*
* Convert Gregorian date to seconds since 01-01-1970 00:00:00.
+ * Safe version for 2038 safety.
+ */
+int rtc_tm_to_time64(struct rtc_time *tm, time64_t *time)
+{
+ *time = mktime64(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ return 0;
+}
+EXPORT_SYMBOL(rtc_tm_to_time64);
+
+/*
+ * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
+ * TODO: [2038 safety] should be replaced by rtc_tm_to_time64.
*/
int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
{
- *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ *time = (unsigned long) mktime64(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
return 0;
}
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index c2c2897..2a6a9ce 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -19,6 +19,7 @@
extern int rtc_month_days(unsigned int month, unsigned int year);
extern int rtc_year_days(unsigned int day, unsigned int month, unsigned int year);
extern int rtc_valid_tm(struct rtc_time *tm);
+extern int rtc_tm_to_time64(struct rtc_time *tm, time64_t *time);
extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time);
extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
ktime_t rtc_tm_to_ktime(struct rtc_time tm);
--
1.7.9.5
As part of addressing 2038 saftey for in-kernel uses, this patch
adds safe rtc_time_to_tm64() using time64_t. After this patch,
rtc_time_to_tm() should be replaced by rtc_time_to_tm64() one by
one. Eventually, rtc_time_to_tm() will be removed from the kernel
when it has no users.
Signed-off-by: pang.xunlei <[email protected]>
---
drivers/rtc/rtc-lib.c | 20 ++++++++++++++++----
include/linux/rtc.h | 1 +
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
index 6948cbd..e84e3a0 100644
--- a/drivers/rtc/rtc-lib.c
+++ b/drivers/rtc/rtc-lib.c
@@ -45,15 +45,17 @@ int rtc_year_days(unsigned int day, unsigned int month, unsigned int year)
}
EXPORT_SYMBOL(rtc_year_days);
+
/*
* Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
+ * Safe version for 2038 safety.
*/
-void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
+void rtc_time_to_tm64(time64_t time, struct rtc_time *tm)
{
unsigned int month, year;
int days;
- days = time / 86400;
+ days = div_s64(time, 86400);
time -= (unsigned int) days * 86400;
/* day of the week, 1970-01-01 was a Thursday */
@@ -81,13 +83,23 @@ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
tm->tm_mon = month;
tm->tm_mday = days + 1;
- tm->tm_hour = time / 3600;
+ tm->tm_hour = div_s64(time, 3600);
time -= tm->tm_hour * 3600;
- tm->tm_min = time / 60;
+ tm->tm_min = div_s64(time, 60);
tm->tm_sec = time - tm->tm_min * 60;
tm->tm_isdst = 0;
}
+EXPORT_SYMBOL(rtc_time_to_tm64);
+
+/* TODO: [2038 safety] should be replaced by rtc_time_to_tm64() */
+void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
+{
+ time64_t time64;
+
+ time64 = (time64_t)time;
+ rtc_time_to_tm64(time64, tm);
+}
EXPORT_SYMBOL(rtc_time_to_tm);
/*
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 2a6a9ce..12bacba 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -21,6 +21,7 @@ extern int rtc_year_days(unsigned int day, unsigned int month, unsigned int year
extern int rtc_valid_tm(struct rtc_time *tm);
extern int rtc_tm_to_time64(struct rtc_time *tm, time64_t *time);
extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time);
+extern void rtc_time_to_tm64(time64_t time, struct rtc_time *tm);
extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
ktime_t rtc_tm_to_ktime(struct rtc_time tm);
struct rtc_time rtc_ktime_to_tm(ktime_t kt);
--
1.7.9.5
As part of addressing 2038 saftey for in-kernel uses, this patch
converts all users of do_settimeofday() to use do_settimeofday64().
This patch also converts rtc_tm_to_time() to rtc_tm_to_time64(),
rtc_time_to_tm() to rtc_time_to_tm64() when needed.
Additionally, changes time64_t definition in time64.h to avoid warnings.
Signed-off-by: pang.xunlei <[email protected]>
---
arch/x86/xen/time.c | 9 +++++++--
drivers/hv/hv_util.c | 6 +++---
drivers/rtc/hctosys.c | 10 +++++-----
drivers/staging/android/alarm-dev.c | 7 +++++--
include/linux/time64.h | 4 ++--
kernel/compat.c | 5 ++++-
kernel/time/time.c | 13 ++++++++++---
7 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index f473d26..16fce39 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -486,6 +486,7 @@ static void __init xen_time_init(void)
{
int cpu = smp_processor_id();
struct timespec tp;
+ struct timespec64 tp64;
clocksource_register_hz(&xen_clocksource, NSEC_PER_SEC);
@@ -496,9 +497,13 @@ static void __init xen_time_init(void)
xen_clockevent = &xen_vcpuop_clockevent;
}
- /* Set initial system time with full resolution */
+ /*
+ * Set initial system time with full resolution
+ * TODO: [2038 safety] xen_read_wallclock() uses timespec64
+ */
xen_read_wallclock(&tp);
- do_settimeofday(&tp);
+ tp64 = timespec_to_timespec64(tp);
+ do_settimeofday64(&tp64);
setup_force_cpu_cap(X86_FEATURE_TSC);
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 3b9c9ef..c91167e 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -166,12 +166,12 @@ static void shutdown_onchannelcallback(void *context)
static inline void do_adj_guesttime(u64 hosttime)
{
s64 host_tns;
- struct timespec host_ts;
+ struct timespec64 host_ts;
host_tns = (hosttime - WLTIMEDELTA) * 100;
- host_ts = ns_to_timespec(host_tns);
+ host_ts = ns_to_timespec64(host_tns);
- do_settimeofday(&host_ts);
+ do_settimeofday64(&host_ts);
}
/*
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c
index 4aa60d7..239400a 100644
--- a/drivers/rtc/hctosys.c
+++ b/drivers/rtc/hctosys.c
@@ -26,7 +26,7 @@ static int __init rtc_hctosys(void)
{
int err = -ENODEV;
struct rtc_time tm;
- struct timespec tv = {
+ struct timespec64 tv = {
.tv_nsec = NSEC_PER_SEC >> 1,
};
struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
@@ -52,16 +52,16 @@ static int __init rtc_hctosys(void)
goto err_invalid;
}
- rtc_tm_to_time(&tm, &tv.tv_sec);
+ rtc_tm_to_time64(&tm, &tv.tv_sec);
- err = do_settimeofday(&tv);
+ err = do_settimeofday64(&tv);
dev_info(rtc->dev.parent,
"setting system clock to "
- "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n",
+ "%d-%02d-%02d %02d:%02d:%02d UTC (%llu)\n",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec,
- (unsigned int) tv.tv_sec);
+ (unsigned long long) tv.tv_sec);
err_invalid:
err_read:
diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c
index ff4b3e8..01017ff 100644
--- a/drivers/staging/android/alarm-dev.c
+++ b/drivers/staging/android/alarm-dev.c
@@ -152,16 +152,19 @@ static int alarm_wait(void)
return rv;
}
+/* TODO: [2038 safety] alarm_set_rtc() uses timespec64 */
static int alarm_set_rtc(struct timespec *ts)
{
+ struct timespec ts64;
struct rtc_time new_rtc_tm;
struct rtc_device *rtc_dev;
unsigned long flags;
int rv = 0;
- rtc_time_to_tm(ts->tv_sec, &new_rtc_tm);
+ ts64 = timespec_to_timespec64(*ts);
+ rtc_time_to_tm64(ts64.tv_sec, &new_rtc_tm);
rtc_dev = alarmtimer_get_rtcdev();
- rv = do_settimeofday(ts);
+ rv = do_settimeofday64(&ts64);
if (rv < 0)
return rv;
if (rtc_dev)
diff --git a/include/linux/time64.h b/include/linux/time64.h
index a383147..2f0cde4 100644
--- a/include/linux/time64.h
+++ b/include/linux/time64.h
@@ -3,15 +3,15 @@
#include <uapi/linux/time.h>
-typedef __s64 time64_t;
-
/*
* This wants to go into uapi/linux/time.h once we agreed about the
* userspace interfaces.
*/
#if __BITS_PER_LONG == 64
+typedef __kernel_time_t time64_t;
# define timespec64 timespec
#else
+typedef __s64 time64_t;
struct timespec64 {
time64_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
diff --git a/kernel/compat.c b/kernel/compat.c
index ebb3c36..29d3234 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -1047,6 +1047,7 @@ COMPAT_SYSCALL_DEFINE1(time, compat_time_t __user *, tloc)
COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
{
struct timespec tv;
+ struct timespec64 tv64;
int err;
if (get_user(tv.tv_sec, tptr))
@@ -1054,11 +1055,13 @@ COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
tv.tv_nsec = 0;
+ /* TODO: [2038 safety] security_settime() uses timespec64 */
err = security_settime(&tv, NULL);
if (err)
return err;
- do_settimeofday(&tv);
+ tv64 = timespec_to_timespec64(tv);
+ do_settimeofday64(&tv64);
return 0;
}
diff --git a/kernel/time/time.c b/kernel/time/time.c
index f44efdb..5074b9b 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -82,6 +82,7 @@ SYSCALL_DEFINE1(time, time_t __user *, tloc)
SYSCALL_DEFINE1(stime, time_t __user *, tptr)
{
struct timespec tv;
+ struct timespec64 tv64;
int err;
if (get_user(tv.tv_sec, tptr))
@@ -93,7 +94,8 @@ SYSCALL_DEFINE1(stime, time_t __user *, tptr)
if (err)
return err;
- do_settimeofday(&tv);
+ tv64 = timespec_to_timespec64(tv);
+ do_settimeofday64(&tv64);
return 0;
}
@@ -162,6 +164,7 @@ static inline void warp_clock(void)
int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz)
{
+ struct timespec64 tv64;
static int firsttime = 1;
int error = 0;
@@ -181,8 +184,12 @@ int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz)
warp_clock();
}
}
- if (tv)
- return do_settimeofday(tv);
+
+ if (tv) {
+ tv64 = timespec_to_timespec64(*tv);
+ return do_settimeofday64(&tv64);
+ }
+
return 0;
}
--
1.7.9.5
Remove do_settimeofday(), since it has no users by now.
Signed-off-by: pang.xunlei <[email protected]>
---
include/linux/timekeeping.h | 1 -
kernel/time/timekeeping.c | 16 ----------------
2 files changed, 17 deletions(-)
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h
index afc61c3..24abc46 100644
--- a/include/linux/timekeeping.h
+++ b/include/linux/timekeeping.h
@@ -11,7 +11,6 @@ extern int timekeeping_suspended;
*/
extern void do_gettimeofday(struct timeval *tv);
extern int do_settimeofday64(const struct timespec64 *ts);
-extern int do_settimeofday(const struct timespec *tv);
extern int do_sys_settimeofday(const struct timespec *tv,
const struct timezone *tz);
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index f0dcbc0..e776d6b 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -744,22 +744,6 @@ int do_settimeofday64(const struct timespec64 *ts)
EXPORT_SYMBOL(do_settimeofday64);
/**
- * do_settimeofday - Sets the time of day
- * @tv: pointer to the timespec variable containing the new time
- *
- * Sets the time of day to the new time and update NTP and notify hrtimers
- * TODO: [2038 safety] should be replaced by do_settimeofday64().
- */
-int do_settimeofday(const struct timespec *tv)
-{
- struct timespec64 ts64;
-
- ts64 = timespec_to_timespec64(*tv);
- return do_settimeofday64(&ts64);
-}
-EXPORT_SYMBOL(do_settimeofday);
-
-/**
* timekeeping_inject_offset - Adds or subtracts from the current time.
* @tv: pointer to the timespec variable containing the offset
*
--
1.7.9.5
As part of addressing 2038 safety for in-kernel uses, this patch
creates no functional change, converts xen_read_wallclock() to
use timespec64 instead of timespec.
Signed-off-by: pang.xunlei <[email protected]>
---
arch/x86/xen/time.c | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 16fce39..4e14439 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -169,20 +169,27 @@ static cycle_t xen_clocksource_get_cycles(struct clocksource *cs)
return xen_clocksource_read();
}
-static void xen_read_wallclock(struct timespec *ts)
+static void xen_read_wallclock(struct timespec64 *ts)
{
+ struct timespec ts_unsafe;
struct shared_info *s = HYPERVISOR_shared_info;
struct pvclock_wall_clock *wall_clock = &(s->wc);
struct pvclock_vcpu_time_info *vcpu_time;
vcpu_time = &get_cpu_var(xen_vcpu)->time;
- pvclock_read_wallclock(wall_clock, vcpu_time, ts);
+ /* TODO: [2038 safety] pvclock_read_wallclock() uses timespec64 */
+ pvclock_read_wallclock(wall_clock, vcpu_time, &ts_unsafe);
+ *ts = timespec_to_timespec64(ts_unsafe);
put_cpu_var(xen_vcpu);
}
+/* TODO: [2038 safety] xen_get_wallclock() uses timespec64 */
static void xen_get_wallclock(struct timespec *now)
{
- xen_read_wallclock(now);
+ struct timespec64 now64;
+
+ xen_read_wallclock(&now64);
+ *now = timespec64_to_timespec(now64);
}
static int xen_set_wallclock(const struct timespec *now)
@@ -485,8 +492,7 @@ static const struct pv_time_ops xen_time_ops __initconst = {
static void __init xen_time_init(void)
{
int cpu = smp_processor_id();
- struct timespec tp;
- struct timespec64 tp64;
+ struct timespec64 tp;
clocksource_register_hz(&xen_clocksource, NSEC_PER_SEC);
@@ -497,13 +503,8 @@ static void __init xen_time_init(void)
xen_clockevent = &xen_vcpuop_clockevent;
}
- /*
- * Set initial system time with full resolution
- * TODO: [2038 safety] xen_read_wallclock() uses timespec64
- */
xen_read_wallclock(&tp);
- tp64 = timespec_to_timespec64(tp);
- do_settimeofday64(&tp64);
+ do_settimeofday64(&tp);
setup_force_cpu_cap(X86_FEATURE_TSC);
--
1.7.9.5
As part of addressing 2038 saftey for in-kernel uses, this patch
creates no functional change, and converts alarm_set_rtc() to use
timespec64.
Signed-off-by: pang.xunlei <[email protected]>
---
drivers/staging/android/alarm-dev.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c
index 01017ff..dfa24f0 100644
--- a/drivers/staging/android/alarm-dev.c
+++ b/drivers/staging/android/alarm-dev.c
@@ -152,19 +152,16 @@ static int alarm_wait(void)
return rv;
}
-/* TODO: [2038 safety] alarm_set_rtc() uses timespec64 */
-static int alarm_set_rtc(struct timespec *ts)
+static int alarm_set_rtc(struct timespec64 *ts)
{
- struct timespec ts64;
struct rtc_time new_rtc_tm;
struct rtc_device *rtc_dev;
unsigned long flags;
int rv = 0;
- ts64 = timespec_to_timespec64(*ts);
- rtc_time_to_tm64(ts64.tv_sec, &new_rtc_tm);
+ rtc_time_to_tm64(ts->tv_sec, &new_rtc_tm);
rtc_dev = alarmtimer_get_rtcdev();
- rv = do_settimeofday64(&ts64);
+ rv = do_settimeofday64(ts);
if (rv < 0)
return rv;
if (rtc_dev)
@@ -201,9 +198,14 @@ static int alarm_get_time(enum android_alarm_type alarm_type,
return rv;
}
+/*
+* TODO: [2038 safety] alarm_do_ioctl() should be fixed to use timespec64,
+* once timespec64 is promoted to userspace.
+*/
static long alarm_do_ioctl(struct file *file, unsigned int cmd,
struct timespec *ts)
{
+ struct timespec64 ts64;
int rv = 0;
unsigned long flags;
enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
@@ -241,7 +243,8 @@ static long alarm_do_ioctl(struct file *file, unsigned int cmd,
rv = alarm_wait();
break;
case ANDROID_ALARM_SET_RTC:
- rv = alarm_set_rtc(ts);
+ ts64 = timespec_to_timespec64(*ts);
+ rv = alarm_set_rtc(&ts64);
break;
case ANDROID_ALARM_GET_TIME(0):
rv = alarm_get_time(alarm_type, ts);
--
1.7.9.5
As part of addressing 2038 safety for in-kernel uses, this patch
creates no functional change, converts pvclock_read_wallclock()
to use timespec64 instead of timespec.
Signed-off-by: pang.xunlei <[email protected]>
---
arch/x86/include/asm/pvclock.h | 2 +-
arch/x86/kernel/kvmclock.c | 7 +++++--
arch/x86/kernel/pvclock.c | 9 +++++----
arch/x86/xen/time.c | 7 ++-----
4 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h
index d6b078e..3323413 100644
--- a/arch/x86/include/asm/pvclock.h
+++ b/arch/x86/include/asm/pvclock.h
@@ -11,7 +11,7 @@ void pvclock_set_flags(u8 flags);
unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src);
void pvclock_read_wallclock(struct pvclock_wall_clock *wall,
struct pvclock_vcpu_time_info *vcpu,
- struct timespec *ts);
+ struct timespec64 *ts);
void pvclock_resume(void);
void pvclock_touch_watchdogs(void);
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index d9156ce..7cd3511 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -46,10 +46,12 @@ static struct pvclock_wall_clock wall_clock;
/*
* The wallclock is the time of day when we booted. Since then, some time may
* have elapsed since the hypervisor wrote the data. So we try to account for
- * that with system time
+ * that with system time.
+ * TODO: [2038 safety] kvm_get_wallclock() should be fixed to use timespec64.
*/
static void kvm_get_wallclock(struct timespec *now)
{
+ struct timespec64 now64;
struct pvclock_vcpu_time_info *vcpu_time;
int low, high;
int cpu;
@@ -63,7 +65,8 @@ static void kvm_get_wallclock(struct timespec *now)
cpu = smp_processor_id();
vcpu_time = &hv_clock[cpu].pvti;
- pvclock_read_wallclock(&wall_clock, vcpu_time, now);
+ pvclock_read_wallclock(&wall_clock, vcpu_time, &now64);
+ *now = timespec64_to_timespec(now64);
preempt_enable();
}
diff --git a/arch/x86/kernel/pvclock.c b/arch/x86/kernel/pvclock.c
index 2f355d2..8e9bbe9 100644
--- a/arch/x86/kernel/pvclock.c
+++ b/arch/x86/kernel/pvclock.c
@@ -117,17 +117,18 @@ cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
void pvclock_read_wallclock(struct pvclock_wall_clock *wall_clock,
struct pvclock_vcpu_time_info *vcpu_time,
- struct timespec *ts)
+ struct timespec64 *ts)
{
u32 version;
u64 delta;
- struct timespec now;
+ struct timespec64 now;
/* get wallclock at system boot */
do {
version = wall_clock->version;
rmb(); /* fetch version before time */
- now.tv_sec = wall_clock->sec;
+ /* TODO: [2038 safety] wall_clock->sec uses time64_t */
+ now.tv_sec = (time64_t)wall_clock->sec;
now.tv_nsec = wall_clock->nsec;
rmb(); /* fetch time before checking version */
} while ((wall_clock->version & 1) || (version != wall_clock->version));
@@ -138,7 +139,7 @@ void pvclock_read_wallclock(struct pvclock_wall_clock *wall_clock,
now.tv_nsec = do_div(delta, NSEC_PER_SEC);
now.tv_sec = delta;
- set_normalized_timespec(ts, now.tv_sec, now.tv_nsec);
+ set_normalized_timespec64(ts, now.tv_sec, now.tv_nsec);
}
#ifdef CONFIG_X86_64
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 4e14439..79053ee 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -171,15 +171,12 @@ static cycle_t xen_clocksource_get_cycles(struct clocksource *cs)
static void xen_read_wallclock(struct timespec64 *ts)
{
- struct timespec ts_unsafe;
struct shared_info *s = HYPERVISOR_shared_info;
struct pvclock_wall_clock *wall_clock = &(s->wc);
- struct pvclock_vcpu_time_info *vcpu_time;
+ struct pvclock_vcpu_time_info *vcpu_time;
vcpu_time = &get_cpu_var(xen_vcpu)->time;
- /* TODO: [2038 safety] pvclock_read_wallclock() uses timespec64 */
- pvclock_read_wallclock(wall_clock, vcpu_time, &ts_unsafe);
- *ts = timespec_to_timespec64(ts_unsafe);
+ pvclock_read_wallclock(wall_clock, vcpu_time, ts);
put_cpu_var(xen_vcpu);
}
--
1.7.9.5
As part of addressing 2038 saftey for in-kernel uses, this patch
creates no functional change, converts x86_platform.set_wallclock()
to use timespec64.
Signed-off-by: pang.xunlei <[email protected]>
---
arch/x86/include/asm/intel_mid_vrtc.h | 2 +-
arch/x86/include/asm/mc146818rtc.h | 2 +-
arch/x86/include/asm/x86_init.h | 3 ++-
arch/x86/kernel/kvmclock.c | 2 +-
arch/x86/kernel/rtc.c | 16 ++++++++++------
arch/x86/platform/intel-mid/intel_mid_vrtc.c | 8 ++++----
arch/x86/xen/time.c | 2 +-
7 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/arch/x86/include/asm/intel_mid_vrtc.h b/arch/x86/include/asm/intel_mid_vrtc.h
index 86ff468..6ad9082 100644
--- a/arch/x86/include/asm/intel_mid_vrtc.h
+++ b/arch/x86/include/asm/intel_mid_vrtc.h
@@ -4,6 +4,6 @@
extern unsigned char vrtc_cmos_read(unsigned char reg);
extern void vrtc_cmos_write(unsigned char val, unsigned char reg);
extern void vrtc_get_time(struct timespec *now);
-extern int vrtc_set_mmss(const struct timespec *now);
+extern int vrtc_set_mmss(const struct timespec64 *now);
#endif
diff --git a/arch/x86/include/asm/mc146818rtc.h b/arch/x86/include/asm/mc146818rtc.h
index 0f555cc..ca88a23 100644
--- a/arch/x86/include/asm/mc146818rtc.h
+++ b/arch/x86/include/asm/mc146818rtc.h
@@ -95,7 +95,7 @@ static inline unsigned char current_lock_cmos_reg(void)
unsigned char rtc_cmos_read(unsigned char addr);
void rtc_cmos_write(unsigned char val, unsigned char addr);
-extern int mach_set_rtc_mmss(const struct timespec *now);
+extern int mach_set_rtc_mmss(const struct timespec64 *now);
extern void mach_get_cmos_time(struct timespec *now);
#define RTC_IRQ 8
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index e45e4da..83ed049 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -143,6 +143,7 @@ struct x86_cpuinit_ops {
};
struct timespec;
+struct timespec64;
/**
* struct x86_platform_ops - platform specific runtime functions
@@ -159,7 +160,7 @@ struct timespec;
struct x86_platform_ops {
unsigned long (*calibrate_tsc)(void);
void (*get_wallclock)(struct timespec *ts);
- int (*set_wallclock)(const struct timespec *ts);
+ int (*set_wallclock)(const struct timespec64 *ts);
void (*iommu_shutdown)(void);
bool (*is_untracked_pat_range)(u64 start, u64 end);
void (*nmi_init)(void);
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index 7cd3511..e51e1eb 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -71,7 +71,7 @@ static void kvm_get_wallclock(struct timespec *now)
preempt_enable();
}
-static int kvm_set_wallclock(const struct timespec *now)
+static int kvm_set_wallclock(const struct timespec64 *now)
{
return -1;
}
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index ca9622a..2bf87a7 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -38,13 +38,13 @@ EXPORT_SYMBOL(rtc_lock);
* jump to the next second precisely 500 ms later. Check the Motorola
* MC146818A or Dallas DS12887 data sheet for details.
*/
-int mach_set_rtc_mmss(const struct timespec *now)
+int mach_set_rtc_mmss(const struct timespec64 *now)
{
- unsigned long nowtime = now->tv_sec;
+ time64_t nowtime = now->tv_sec;
struct rtc_time tm;
int retval = 0;
- rtc_time_to_tm(nowtime, &tm);
+ rtc_time_to_tm64(nowtime, &tm);
if (!rtc_valid_tm(&tm)) {
retval = set_rtc_time(&tm);
if (retval)
@@ -52,8 +52,8 @@ int mach_set_rtc_mmss(const struct timespec *now)
__FUNCTION__, retval);
} else {
printk(KERN_ERR
- "%s: Invalid RTC value: write of %lx to RTC failed\n",
- __FUNCTION__, nowtime);
+ "%s: Invalid RTC value: write of %llx to RTC failed\n",
+ __FUNCTION__, (unsigned long long)nowtime);
retval = -EINVAL;
}
return retval;
@@ -135,9 +135,13 @@ void rtc_cmos_write(unsigned char val, unsigned char addr)
}
EXPORT_SYMBOL(rtc_cmos_write);
+/* TODO: [2038 safety] update_persistent_clock() uses timespec64 */
int update_persistent_clock(struct timespec now)
{
- return x86_platform.set_wallclock(&now);
+ struct timespec64 now64;
+
+ now64 = timespec_to_timespec64(now);
+ return x86_platform.set_wallclock(&now64);
}
/* not static: needed by APM */
diff --git a/arch/x86/platform/intel-mid/intel_mid_vrtc.c b/arch/x86/platform/intel-mid/intel_mid_vrtc.c
index 4762cff..a370b83 100644
--- a/arch/x86/platform/intel-mid/intel_mid_vrtc.c
+++ b/arch/x86/platform/intel-mid/intel_mid_vrtc.c
@@ -86,14 +86,14 @@ void vrtc_get_time(struct timespec *now)
now->tv_nsec = 0;
}
-int vrtc_set_mmss(const struct timespec *now)
+int vrtc_set_mmss(const struct timespec64 *now)
{
unsigned long flags;
struct rtc_time tm;
int year;
int retval = 0;
- rtc_time_to_tm(now->tv_sec, &tm);
+ rtc_time_to_tm64(now->tv_sec, &tm);
if (!rtc_valid_tm(&tm) && tm.tm_year >= 72) {
/*
* tm.year is the number of years since 1900, and the
@@ -109,8 +109,8 @@ int vrtc_set_mmss(const struct timespec *now)
vrtc_cmos_write(tm.tm_sec, RTC_SECONDS);
spin_unlock_irqrestore(&rtc_lock, flags);
} else {
- pr_err("%s: Invalid vRTC value: write of %lx to vRTC failed\n",
- __FUNCTION__, now->tv_sec);
+ pr_err("%s: Invalid vRTC value: write of %llx to vRTC failed\n",
+ __FUNCTION__, (unsigned long long)now->tv_sec);
retval = -EINVAL;
}
return retval;
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 79053ee..b30ed24 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -189,7 +189,7 @@ static void xen_get_wallclock(struct timespec *now)
*now = timespec64_to_timespec(now64);
}
-static int xen_set_wallclock(const struct timespec *now)
+static int xen_set_wallclock(const struct timespec64 *now)
{
return -1;
}
--
1.7.9.5
As part of addressing 2038 saftey for in-kernel uses, this patch
creates no functional change, converts x86_platform.get_wallclock()
to use timespec64. Also changes time64.h to avoid build warnings.
Signed-off-by: pang.xunlei <[email protected]>
---
arch/x86/include/asm/intel_mid_vrtc.h | 2 +-
arch/x86/include/asm/mc146818rtc.h | 2 +-
arch/x86/include/asm/x86_init.h | 8 +++++---
arch/x86/kernel/kvmclock.c | 7 ++-----
arch/x86/kernel/rtc.c | 14 ++++++++++----
arch/x86/lguest/boot.c | 4 ++--
arch/x86/platform/intel-mid/intel_mid_vrtc.c | 4 ++--
arch/x86/xen/time.c | 8 ++------
include/linux/lguest.h | 2 +-
include/linux/time64.h | 1 +
10 files changed, 27 insertions(+), 25 deletions(-)
diff --git a/arch/x86/include/asm/intel_mid_vrtc.h b/arch/x86/include/asm/intel_mid_vrtc.h
index 6ad9082..1920232 100644
--- a/arch/x86/include/asm/intel_mid_vrtc.h
+++ b/arch/x86/include/asm/intel_mid_vrtc.h
@@ -3,7 +3,7 @@
extern unsigned char vrtc_cmos_read(unsigned char reg);
extern void vrtc_cmos_write(unsigned char val, unsigned char reg);
-extern void vrtc_get_time(struct timespec *now);
+extern void vrtc_get_time(struct timespec64 *now);
extern int vrtc_set_mmss(const struct timespec64 *now);
#endif
diff --git a/arch/x86/include/asm/mc146818rtc.h b/arch/x86/include/asm/mc146818rtc.h
index ca88a23..40355e4 100644
--- a/arch/x86/include/asm/mc146818rtc.h
+++ b/arch/x86/include/asm/mc146818rtc.h
@@ -96,7 +96,7 @@ unsigned char rtc_cmos_read(unsigned char addr);
void rtc_cmos_write(unsigned char val, unsigned char addr);
extern int mach_set_rtc_mmss(const struct timespec64 *now);
-extern void mach_get_cmos_time(struct timespec *now);
+extern void mach_get_cmos_time(struct timespec64 *now);
#define RTC_IRQ 8
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 83ed049..fded1e4 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -142,9 +142,11 @@ struct x86_cpuinit_ops {
void (*fixup_cpu_id)(struct cpuinfo_x86 *c, int node);
};
-struct timespec;
+#ifdef CONFIG_64BIT
+#include <linux/time64.h>
+#else
struct timespec64;
-
+#endif
/**
* struct x86_platform_ops - platform specific runtime functions
* @calibrate_tsc: calibrate TSC
@@ -159,7 +161,7 @@ struct timespec64;
*/
struct x86_platform_ops {
unsigned long (*calibrate_tsc)(void);
- void (*get_wallclock)(struct timespec *ts);
+ void (*get_wallclock)(struct timespec64 *ts);
int (*set_wallclock)(const struct timespec64 *ts);
void (*iommu_shutdown)(void);
bool (*is_untracked_pat_range)(u64 start, u64 end);
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index e51e1eb..c19ffc7 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -47,11 +47,9 @@ static struct pvclock_wall_clock wall_clock;
* The wallclock is the time of day when we booted. Since then, some time may
* have elapsed since the hypervisor wrote the data. So we try to account for
* that with system time.
- * TODO: [2038 safety] kvm_get_wallclock() should be fixed to use timespec64.
*/
-static void kvm_get_wallclock(struct timespec *now)
+static void kvm_get_wallclock(struct timespec64 *now)
{
- struct timespec64 now64;
struct pvclock_vcpu_time_info *vcpu_time;
int low, high;
int cpu;
@@ -65,8 +63,7 @@ static void kvm_get_wallclock(struct timespec *now)
cpu = smp_processor_id();
vcpu_time = &hv_clock[cpu].pvti;
- pvclock_read_wallclock(&wall_clock, vcpu_time, &now64);
- *now = timespec64_to_timespec(now64);
+ pvclock_read_wallclock(&wall_clock, vcpu_time, now);
preempt_enable();
}
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index 2bf87a7..a142180 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -59,7 +59,7 @@ int mach_set_rtc_mmss(const struct timespec64 *now)
return retval;
}
-void mach_get_cmos_time(struct timespec *now)
+void mach_get_cmos_time(struct timespec64 *now)
{
unsigned int status, year, mon, day, hour, min, sec, century = 0;
unsigned long flags;
@@ -108,7 +108,7 @@ void mach_get_cmos_time(struct timespec *now)
} else
year += CMOS_YEARS_OFFS;
- now->tv_sec = mktime(year, mon, day, hour, min, sec);
+ now->tv_sec = mktime64(year, mon, day, hour, min, sec);
now->tv_nsec = 0;
}
@@ -144,10 +144,16 @@ int update_persistent_clock(struct timespec now)
return x86_platform.set_wallclock(&now64);
}
-/* not static: needed by APM */
+/*
+ * not static: needed by APM.
+ * TODO: [2038 safety] read_persistent_clock() uses timespec64.
+ */
void read_persistent_clock(struct timespec *ts)
{
- x86_platform.get_wallclock(ts);
+ struct timespec ts64;
+
+ x86_platform.get_wallclock(&ts64);
+ *ts = timespec64_to_timespec(ts64);
}
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index aae9413..4d2ccb6 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -881,9 +881,9 @@ int lguest_setup_irq(unsigned int irq)
* It would be far better for everyone if the Guest had its own clock, but
* until then the Host gives us the time on every interrupt.
*/
-static void lguest_get_wallclock(struct timespec *now)
+static void lguest_get_wallclock(struct timespec64 *now)
{
- *now = lguest_data.time;
+ *now = timespec_to_timespec64(lguest_data.time);
}
/*
diff --git a/arch/x86/platform/intel-mid/intel_mid_vrtc.c b/arch/x86/platform/intel-mid/intel_mid_vrtc.c
index a370b83..dbd540c 100644
--- a/arch/x86/platform/intel-mid/intel_mid_vrtc.c
+++ b/arch/x86/platform/intel-mid/intel_mid_vrtc.c
@@ -56,7 +56,7 @@ void vrtc_cmos_write(unsigned char val, unsigned char reg)
}
EXPORT_SYMBOL_GPL(vrtc_cmos_write);
-void vrtc_get_time(struct timespec *now)
+void vrtc_get_time(struct timespec64 *now)
{
u8 sec, min, hour, mday, mon;
unsigned long flags;
@@ -82,7 +82,7 @@ void vrtc_get_time(struct timespec *now)
pr_info("vRTC: sec: %d min: %d hour: %d day: %d "
"mon: %d year: %d\n", sec, min, hour, mday, mon, year);
- now->tv_sec = mktime(year, mon, mday, hour, min, sec);
+ now->tv_sec = mktime64(year, mon, mday, hour, min, sec);
now->tv_nsec = 0;
}
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index b30ed24..dd35a3e 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -180,13 +180,9 @@ static void xen_read_wallclock(struct timespec64 *ts)
put_cpu_var(xen_vcpu);
}
-/* TODO: [2038 safety] xen_get_wallclock() uses timespec64 */
-static void xen_get_wallclock(struct timespec *now)
+static void xen_get_wallclock(struct timespec64 *now)
{
- struct timespec64 now64;
-
- xen_read_wallclock(&now64);
- *now = timespec64_to_timespec(now64);
+ xen_read_wallclock(now);
}
static int xen_set_wallclock(const struct timespec64 *now)
diff --git a/include/linux/lguest.h b/include/linux/lguest.h
index 9962c6b..1640121 100644
--- a/include/linux/lguest.h
+++ b/include/linux/lguest.h
@@ -35,7 +35,7 @@ struct lguest_data {
unsigned long cr2;
/* Wallclock time set by the Host. */
- struct timespec time;
+ struct timespec time; /* TODO: [2038 safety] to use timespec64 */
/*
* Interrupt pending set by the Host. The Guest should do a hypercall
diff --git a/include/linux/time64.h b/include/linux/time64.h
index 2f0cde4..f2172e4 100644
--- a/include/linux/time64.h
+++ b/include/linux/time64.h
@@ -57,6 +57,7 @@ static inline struct timespec64 timespec_to_timespec64(const struct timespec ts)
#else
+#include <linux/math64.h>
static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64)
{
struct timespec ret;
--
1.7.9.5
On Thu, 30 Oct 2014, pang.xunlei wrote:
Your subject line
> time: Add do_settimeofday64() safe version(using timespec64)
is confusing at best.
time: Provide y2038 safe do_settimeofday() replacement
That explains what the patch is doing in a very precice way.
> /**
> - * do_settimeofday - Sets the time of day
> - * @tv: pointer to the timespec variable containing the new time
> + * do_settimeofday64 - Sets the time of day
> + * @ts: pointer to the timespec64 variable containing the new time
> *
> * Sets the time of day to the new time and update NTP and notify hrtimers
> + * Safe version for 2038 safety.
I rather put this into the function description above:
+ * do_settimeofday64 - Sets the time of day. 2038 safe.
Way simpler to grep for.
> */
> -int do_settimeofday(const struct timespec *tv)
> +int do_settimeofday64(const struct timespec64 *ts)
> {
> struct timekeeper *tk = &tk_core.timekeeper;
> - struct timespec64 ts_delta, xt, tmp;
> + struct timespec64 ts_delta, xt;
> unsigned long flags;
>
> - if (!timespec_valid_strict(tv))
> + if (!timespec64_valid_strict(ts))
> return -EINVAL;
>
> raw_spin_lock_irqsave(&timekeeper_lock, flags);
> @@ -723,13 +724,12 @@ int do_settimeofday(const struct timespec *tv)
> timekeeping_forward_now(tk);
>
> xt = tk_xtime(tk);
> - ts_delta.tv_sec = tv->tv_sec - xt.tv_sec;
> - ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec;
> + ts_delta.tv_sec = ts->tv_sec - xt.tv_sec;
> + ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec;
>
> tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta));
>
> - tmp = timespec_to_timespec64(*tv);
> - tk_set_xtime(tk, &tmp);
> + tk_set_xtime(tk, ts);
>
> timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
>
> @@ -741,6 +741,22 @@ int do_settimeofday(const struct timespec *tv)
>
> return 0;
> }
> +EXPORT_SYMBOL(do_settimeofday64);
EXPORT_SYMBOL_GPL please.
> +
> +/**
> + * do_settimeofday - Sets the time of day
> + * @tv: pointer to the timespec variable containing the new time
> + *
> + * Sets the time of day to the new time and update NTP and notify hrtimers
> + * TODO: [2038 safety] should be replaced by do_settimeofday64().
The TODO is not to replace do_settimeofday() by do_settimeofday64(). The TODO
is to fix the call sites.
So instead of adding this you can simply say:
+ * do_settimeofday - Sets the time of day. Deprecated. Use do_settimeofday64()
We want things like this easy to find and not be burried in some
cryptic comment.
Thanks,
tglx
On Thu, 30 Oct 2014, pang.xunlei wrote:
Same problem with the $subject as in the previous patch.
> As part of addressing 2038 saftey for in-kernel uses, this patch
s/saftey/safety/
saftey is something completely different.
> +/*
> + * Converts Gregorian date to seconds since 1970-01-01 00:00:00.
> + * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
> + * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
> + *
> + * [For the Julian calendar (which was used in Russia before 1917,
> + * Britain & colonies before 1752, anywhere else before 1582,
> + * and is still in use by some communities) leave out the
> + * -year/100+year/400 terms, and add 10.]
> + *
> + * This algorithm was first published by Gauss (I think).
> + *
So this blindly copies the comment from mktime but misses to add a
proper docbook comment for the function.
> + * Safe version 2038 safety on 32-bit systems.
This sentence makes no sense at all. Aside of that you want to do the
same as I suggested for do_settimeofday64
* mktime64 - Convert gregrorian date to seconds since 1970. y2038 safe
> + */
> +time64_t
> +mktime64(const unsigned int year0, const unsigned int mon0,
> + const unsigned int day, const unsigned int hour,
> + const unsigned int min, const unsigned int sec)
Make this
time64_t mktime64(const unsigned int year0, const unsigned int mon0,
const unsigned int day, const unsigned int hour,
const unsigned int min, const unsigned int sec)
please.
> +{
> + time64_t ret;
> + unsigned int mon = mon0, year = year0;
I pretty much prefer the following style:
+ unsigned int mon = mon0, year = year0;
+ time64_t ret;
Way simpler to parse.
> + /* 1..12 -> 11,12,1..10 */
> + if (0 >= (int) (mon -= 2)) {
> + mon += 12; /* Puts Feb last since it has leap day */
Please get rid of the tail comments while you are at it:
/* Put Feb last since it has a leap day */
mon += 12;
Again simpler to parse.
> + year -= 1;
> + }
> +
> + ret = (year/4 - year/100 + year/400 + 367*mon/12 + day) + year*365 - 719499;
For readability sake
> + ret = ret*24 + hour; /* now have hours */
Please kill these pointless comments. The calculation above is the one
which could do with a comment not the obvious days to hrs and hrs to
min and min to sec conversions.
We do not blindly copy code and leave the mess unchanged.
> + ret = ret*60 + min; /* now have minutes */
> + ret = ret*60 + sec; /* finally seconds */
> +
> + return ret;
> +}
> +
> +EXPORT_SYMBOL(mktime64);
EXPORT_SYMBOL_GPL please.
> +
> /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
> * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
> * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
> @@ -318,6 +356,7 @@ EXPORT_SYMBOL(timespec_trunc);
> * WARNING: this function will overflow on 2106-02-07 06:28:16 on
> * machines where long is 32-bit! (However, as time_t is signed, we
> * will already get problems at other places on 2038-01-19 03:14:08)
> + * TODO: [2038 safety] should be replaced by mktime64().
> */
> unsigned long
> mktime(const unsigned int year0, const unsigned int mon0,
Why are you keeping this implementation instead of replacing the
comment by a simple one liner
/*
* mktime - Convert gregrorian date to seconds since 1970. Deprecated. Use mktime64
*/
No need to add a full docbook comment as this is going away anyway.
and change the implementation to
{
return mktime64(....);
}
Thanks,
tglx
On Thu, 30 Oct 2014, pang.xunlei wrote:
Same $subject issue.
> As part of addressing 2038 saftey for in-kernel uses, this patch
> adds safe rtc_tm_to_time64() using time64_t. After this patch,
> rtc_tm_to_time() should be replaced by rtc_tm_to_time64() one by
> one. Eventually, rtc_tm_to_time() will be removed from the kernel
> when it has no users.
>
> Signed-off-by: pang.xunlei <[email protected]>
> ---
> drivers/rtc/rtc-lib.c | 15 ++++++++++++++-
> include/linux/rtc.h | 1 +
> 2 files changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
> index c4cf057..6948cbd 100644
> --- a/drivers/rtc/rtc-lib.c
> +++ b/drivers/rtc/rtc-lib.c
> @@ -110,10 +110,23 @@ EXPORT_SYMBOL(rtc_valid_tm);
>
> /*
> * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
> + * Safe version for 2038 safety.
Docbook comment missing. See the previous replies.
> + */
> +int rtc_tm_to_time64(struct rtc_time *tm, time64_t *time)
What's the point of the return value? Just because rtc_tm_to_time()
has one?
Yes it does, but that does not mean that we blindly copy the existing
nonsense when we implement a replacement interface.
What's wrong with changing it to:
time64_t rtc_tm_to_time64(struct rtc_time *tm)
{
return mktime64(......);
}
> +/*
> + * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
> + * TODO: [2038 safety] should be replaced by rtc_tm_to_time64.
Groan.
> */
> int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
> {
> - *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
> + *time = (unsigned long) mktime64(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
> tm->tm_hour, tm->tm_min, tm->tm_sec);
And that would become
*time = rtc_time_to_time64(tm);
> return 0;
> }
Please stop doing purely mechanical changes. Just blindly copying
stuff and make it take time64_t instead of unsigned long can be done
with a script as well.
Thanks,
tglx
On Thu, 30 Oct 2014, pang.xunlei wrote:
As you can guess already: $subject sucks.
> +
> /*
> * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
> + * Safe version for 2038 safety.
See previous replies.
> */
> -void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
> +void rtc_time_to_tm64(time64_t time, struct rtc_time *tm)
What's tm64?
This function is converting time64 to rtc_time. So the proper function
name is: rtc_time64_to_tm
Can you see the difference?
> {
> unsigned int month, year;
> int days;
>
> - days = time / 86400;
> + days = div_s64(time, 86400);
> time -= (unsigned int) days * 86400;
>
> /* day of the week, 1970-01-01 was a Thursday */
> @@ -81,13 +83,23 @@ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
> tm->tm_mon = month;
> tm->tm_mday = days + 1;
>
> - tm->tm_hour = time / 3600;
> + tm->tm_hour = div_s64(time, 3600);
We already adjusted time to a value which is less than 24 * 3600,
i.e. it fits nicely into a long on 32bit. So we can avoid the whole
div_s64 business and simply do:
unsigned int month, year;
+ unsigned long secs;
int days;
- days = time / 86400;
- time -= (unsigned int) days * 86400;
+ days = div_s64(time, 86400);
+ secs = time - (unsigned int) days * 86400;
And change the rest which uses time to:
- tm->tm_hour = time / 3600;
+ tm->tm_hour = secs / 3600;
Sigh.
tglx
On Thu, 30 Oct 2014, pang.xunlei wrote:
> As part of addressing 2038 saftey for in-kernel uses, this patch
> converts all users of do_settimeofday() to use do_settimeofday64().
You forgot to insert 'blindly' between 'converts' and 'all'.
> --- a/arch/x86/xen/time.c
> +++ b/arch/x86/xen/time.c
> @@ -486,6 +486,7 @@ static void __init xen_time_init(void)
> {
> int cpu = smp_processor_id();
> struct timespec tp;
> + struct timespec64 tp64;
>
> clocksource_register_hz(&xen_clocksource, NSEC_PER_SEC);
>
> @@ -496,9 +497,13 @@ static void __init xen_time_init(void)
> xen_clockevent = &xen_vcpuop_clockevent;
> }
>
> - /* Set initial system time with full resolution */
> + /*
> + * Set initial system time with full resolution
> + * TODO: [2038 safety] xen_read_wallclock() uses timespec64
This is the wrong approach, really.
First of all this wants to be a seperate patch. Secondly it wants to
be a patch series which addresses the whole XEN space which is
involved in this. That involves other changes to x86 as well, but we
really can do better than mechanically pushing the problem one step
deeper just to get rid of the non safe do_settimeofday() variant.
It does not matter WHEN we remove that. What matters is that we do the
conversion in sensible contexts and not by mechanically pushing the
problem one layer down, leave cryptic TODO comments around and think
we achieved something.
> diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
> index 3b9c9ef..c91167e 100644
> --- a/drivers/hv/hv_util.c
> +++ b/drivers/hv/hv_util.c
> @@ -166,12 +166,12 @@ static void shutdown_onchannelcallback(void *context)
> static inline void do_adj_guesttime(u64 hosttime)
> {
> s64 host_tns;
> - struct timespec host_ts;
> + struct timespec64 host_ts;
>
> host_tns = (hosttime - WLTIMEDELTA) * 100;
> - host_ts = ns_to_timespec(host_tns);
> + host_ts = ns_to_timespec64(host_tns);
>
> - do_settimeofday(&host_ts);
> + do_settimeofday64(&host_ts);
That part is obvious, but it wants to be a seperate patch.
> /*
> diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c
> index 4aa60d7..239400a 100644
> --- a/drivers/rtc/hctosys.c
> +++ b/drivers/rtc/hctosys.c
> @@ -26,7 +26,7 @@ static int __init rtc_hctosys(void)
> {
> int err = -ENODEV;
> struct rtc_time tm;
> - struct timespec tv = {
> + struct timespec64 tv = {
> .tv_nsec = NSEC_PER_SEC >> 1,
> };
> struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
> @@ -52,16 +52,16 @@ static int __init rtc_hctosys(void)
> goto err_invalid;
> }
>
> - rtc_tm_to_time(&tm, &tv.tv_sec);
> + rtc_tm_to_time64(&tm, &tv.tv_sec);
>
> - err = do_settimeofday(&tv);
> + err = do_settimeofday64(&tv);
>
> dev_info(rtc->dev.parent,
> "setting system clock to "
> - "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n",
> + "%d-%02d-%02d %02d:%02d:%02d UTC (%llu)\n",
> tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
> tm.tm_hour, tm.tm_min, tm.tm_sec,
> - (unsigned int) tv.tv_sec);
> + (unsigned long long) tv.tv_sec);
>
> err_invalid:
> err_read:
Ditto.
> diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c
> index ff4b3e8..01017ff 100644
> --- a/drivers/staging/android/alarm-dev.c
> +++ b/drivers/staging/android/alarm-dev.c
> @@ -152,16 +152,19 @@ static int alarm_wait(void)
> return rv;
> }
>
> +/* TODO: [2038 safety] alarm_set_rtc() uses timespec64 */
> static int alarm_set_rtc(struct timespec *ts)
> {
> + struct timespec ts64;
> struct rtc_time new_rtc_tm;
> struct rtc_device *rtc_dev;
> unsigned long flags;
> int rv = 0;
>
> - rtc_time_to_tm(ts->tv_sec, &new_rtc_tm);
> + ts64 = timespec_to_timespec64(*ts);
> + rtc_time_to_tm64(ts64.tv_sec, &new_rtc_tm);
> rtc_dev = alarmtimer_get_rtcdev();
> - rv = do_settimeofday(ts);
> + rv = do_settimeofday64(&ts64);
John: What kind of weird hackery is that alarm-dev thing? This should
rather die than being fixed.
> if (rv < 0)
> return rv;
> if (rtc_dev)
> diff --git a/include/linux/time64.h b/include/linux/time64.h
> index a383147..2f0cde4 100644
> --- a/include/linux/time64.h
> +++ b/include/linux/time64.h
> @@ -3,15 +3,15 @@
>
> #include <uapi/linux/time.h>
>
> -typedef __s64 time64_t;
> -
> /*
> * This wants to go into uapi/linux/time.h once we agreed about the
> * userspace interfaces.
> */
> #if __BITS_PER_LONG == 64
> +typedef __kernel_time_t time64_t;
> # define timespec64 timespec
> #else
> +typedef __s64 time64_t;
> struct timespec64 {
> time64_t tv_sec; /* seconds */
> long tv_nsec; /* nanoseconds */
This is a completely seperate change and should not be in that patch
at all.
> diff --git a/kernel/compat.c b/kernel/compat.c
> index ebb3c36..29d3234 100644
> --- a/kernel/compat.c
> +++ b/kernel/compat.c
> @@ -1047,6 +1047,7 @@ COMPAT_SYSCALL_DEFINE1(time, compat_time_t __user *, tloc)
> COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
> {
> struct timespec tv;
> + struct timespec64 tv64;
> int err;
>
> if (get_user(tv.tv_sec, tptr))
> @@ -1054,11 +1055,13 @@ COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
>
> tv.tv_nsec = 0;
>
> + /* TODO: [2038 safety] security_settime() uses timespec64 */
Wrong again. Provide security_settime64() first. Then convert this file in one go.
> err = security_settime(&tv, NULL);
> if (err)
> return err;
>
> - do_settimeofday(&tv);
> + tv64 = timespec_to_timespec64(tv);
> + do_settimeofday64(&tv64);
> return 0;
> }
>
> diff --git a/kernel/time/time.c b/kernel/time/time.c
> index f44efdb..5074b9b 100644
> --- a/kernel/time/time.c
> +++ b/kernel/time/time.c
> @@ -82,6 +82,7 @@ SYSCALL_DEFINE1(time, time_t __user *, tloc)
> SYSCALL_DEFINE1(stime, time_t __user *, tptr)
> {
> struct timespec tv;
> + struct timespec64 tv64;
> int err;
>
> if (get_user(tv.tv_sec, tptr))
> @@ -93,7 +94,8 @@ SYSCALL_DEFINE1(stime, time_t __user *, tptr)
> if (err)
> return err;
>
> - do_settimeofday(&tv);
> + tv64 = timespec_to_timespec64(tv);
> + do_settimeofday64(&tv64);
> return 0;
Same here.
> }
>
> @@ -162,6 +164,7 @@ static inline void warp_clock(void)
>
> int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz)
> {
> + struct timespec64 tv64;
> static int firsttime = 1;
> int error = 0;
>
> @@ -181,8 +184,12 @@ int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz)
> warp_clock();
> }
> }
> - if (tv)
> - return do_settimeofday(tv);
> +
> + if (tv) {
> + tv64 = timespec_to_timespec64(*tv);
> + return do_settimeofday64(&tv64);
And here.
And once you converted these 3 files, you can remove
security_settime(). That makes a lot more sense than what you are
trying to do here.
Thanks,
tglx
On Thu, 30 Oct 2014, pang.xunlei wrote:
> +/*
> +* TODO: [2038 safety] alarm_do_ioctl() should be fixed to use timespec64,
> +* once timespec64 is promoted to userspace.
Nonsense. You CANNOT 'FIX' this. The ioctl needs to stay as is because
you need to preserve the user space ABI.
It needs a new ioctl variant which handles timespec64.
Thanks,
tglx
On Thu, 30 Oct 2014, pang.xunlei wrote:
> /* get wallclock at system boot */
> do {
> version = wall_clock->version;
> rmb(); /* fetch version before time */
> - now.tv_sec = wall_clock->sec;
> + /* TODO: [2038 safety] wall_clock->sec uses time64_t */
Wrong. This is part of the hypervisor ABI and you can add as many
TODOs here as you want. They will not change the ABI ever. If XEN
wants to fix that it needs to implement a new hypervisor interface.
> + now.tv_sec = (time64_t)wall_clock->sec;
copy & paste does not solve all these problems magically.
Thanks,
tglx
On Thu, Oct 30, 2014 at 7:49 AM, Thomas Gleixner <[email protected]> wrote:
> On Thu, 30 Oct 2014, pang.xunlei wrote:
>
>> As part of addressing 2038 saftey for in-kernel uses, this patch
>> converts all users of do_settimeofday() to use do_settimeofday64().
>
> You forgot to insert 'blindly' between 'converts' and 'all'.
>
>> --- a/arch/x86/xen/time.c
>> +++ b/arch/x86/xen/time.c
>> @@ -486,6 +486,7 @@ static void __init xen_time_init(void)
>> {
>> int cpu = smp_processor_id();
>> struct timespec tp;
>> + struct timespec64 tp64;
>>
>> clocksource_register_hz(&xen_clocksource, NSEC_PER_SEC);
>>
>> @@ -496,9 +497,13 @@ static void __init xen_time_init(void)
>> xen_clockevent = &xen_vcpuop_clockevent;
>> }
>>
>> - /* Set initial system time with full resolution */
>> + /*
>> + * Set initial system time with full resolution
>> + * TODO: [2038 safety] xen_read_wallclock() uses timespec64
>
> This is the wrong approach, really.
>
> First of all this wants to be a seperate patch. Secondly it wants to
> be a patch series which addresses the whole XEN space which is
> involved in this. That involves other changes to x86 as well, but we
> really can do better than mechanically pushing the problem one step
> deeper just to get rid of the non safe do_settimeofday() variant.
>
> It does not matter WHEN we remove that. What matters is that we do the
> conversion in sensible contexts and not by mechanically pushing the
> problem one layer down, leave cryptic TODO comments around and think
> we achieved something.
So agreed that this patch should be broken up.
And yea, as a side effect of your earlier feedback to add 64bit
interfaces and slowly migrate, I guess it does make sense to handle
all the interfaces first, and then cohesively address each subsystem,
rather then addressing interface by interface through the whole
system. My suggested partitioning of the problem doesn't produce as
nice to understand patches.
That said, this is a big project with a number of folks attacking it,
and as seen in the Xen code (where xen's settime logic bleeds into the
pv persistent clock logic), if we go subsystem by subsystem rather
then interface by interface, there will be cases where subsystems
interact and I think we'll still have to have similar TODOs notes and
iterations. I think having some greppable tag in the comments will
help as we iterate through things.
>> diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c
>> index ff4b3e8..01017ff 100644
>> --- a/drivers/staging/android/alarm-dev.c
>> +++ b/drivers/staging/android/alarm-dev.c
>> @@ -152,16 +152,19 @@ static int alarm_wait(void)
>> return rv;
>> }
>>
>> +/* TODO: [2038 safety] alarm_set_rtc() uses timespec64 */
>> static int alarm_set_rtc(struct timespec *ts)
>> {
>> + struct timespec ts64;
>> struct rtc_time new_rtc_tm;
>> struct rtc_device *rtc_dev;
>> unsigned long flags;
>> int rv = 0;
>>
>> - rtc_time_to_tm(ts->tv_sec, &new_rtc_tm);
>> + ts64 = timespec_to_timespec64(*ts);
>> + rtc_time_to_tm64(ts64.tv_sec, &new_rtc_tm);
>> rtc_dev = alarmtimer_get_rtcdev();
>> - rv = do_settimeofday(ts);
>> + rv = do_settimeofday64(&ts64);
>
> John: What kind of weird hackery is that alarm-dev thing? This should
> rather die than being fixed.
I think it was agreed at plumbers that we can drop alarm-dev from
staging. But if its fixed before its dropped, or just dropped doesn't
matter.
thanks
-john
On Thu, 30 Oct 2014, John Stultz wrote:
> On Thu, Oct 30, 2014 at 7:49 AM, Thomas Gleixner <[email protected]> wrote:
> > First of all this wants to be a seperate patch. Secondly it wants to
> > be a patch series which addresses the whole XEN space which is
> > involved in this. That involves other changes to x86 as well, but we
> > really can do better than mechanically pushing the problem one step
> > deeper just to get rid of the non safe do_settimeofday() variant.
> >
> > It does not matter WHEN we remove that. What matters is that we do the
> > conversion in sensible contexts and not by mechanically pushing the
> > problem one layer down, leave cryptic TODO comments around and think
> > we achieved something.
>
> So agreed that this patch should be broken up.
>
> And yea, as a side effect of your earlier feedback to add 64bit
> interfaces and slowly migrate, I guess it does make sense to handle
> all the interfaces first, and then cohesively address each subsystem,
> rather then addressing interface by interface through the whole
> system. My suggested partitioning of the problem doesn't produce as
> nice to understand patches.
This is very different to the BKL push down, where we really had to
see the context in the particular file/subsystem to understand what it
was actually protecting or not.
> That said, this is a big project with a number of folks attacking it,
> and as seen in the Xen code (where xen's settime logic bleeds into the
> pv persistent clock logic), if we go subsystem by subsystem rather
> then interface by interface, there will be cases where subsystems
> interact and I think we'll still have to have similar TODOs notes and
> iterations. I think having some greppable tag in the comments will
> help as we iterate through things.
That's fine as long as we do not just go blindly and push stuff down
one level deeper w/o looking at the complete call chain first. Doing
the whole x86 rtc related stuff in one series (after the core
interfaces are in place) avoids the whole todo churn nicely.
Interactions are expected, but we should avoid them if possible by
partitioning the patches in a sensible manner.
> > John: What kind of weird hackery is that alarm-dev thing? This should
> > rather die than being fixed.
>
> I think it was agreed at plumbers that we can drop alarm-dev from
> staging. But if its fixed before its dropped, or just dropped doesn't
> matter.
One pointless patch less :)
We really can leave that alone and either kill do_settimeofday() after
its gone or expedite its death by removing do_settimeofday().
Thanks,
tglx
On 30 October 2014 21:55, Thomas Gleixner <[email protected]> wrote:
> On Thu, 30 Oct 2014, pang.xunlei wrote:
>
> Same $subject issue.
>
>> As part of addressing 2038 saftey for in-kernel uses, this patch
>> adds safe rtc_tm_to_time64() using time64_t. After this patch,
>> rtc_tm_to_time() should be replaced by rtc_tm_to_time64() one by
>> one. Eventually, rtc_tm_to_time() will be removed from the kernel
>> when it has no users.
>>
>> Signed-off-by: pang.xunlei <[email protected]>
>> ---
>> drivers/rtc/rtc-lib.c | 15 ++++++++++++++-
>> include/linux/rtc.h | 1 +
>> 2 files changed, 15 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
>> index c4cf057..6948cbd 100644
>> --- a/drivers/rtc/rtc-lib.c
>> +++ b/drivers/rtc/rtc-lib.c
>> @@ -110,10 +110,23 @@ EXPORT_SYMBOL(rtc_valid_tm);
>>
>> /*
>> * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
>> + * Safe version for 2038 safety.
>
> Docbook comment missing. See the previous replies.
>
>> + */
>> +int rtc_tm_to_time64(struct rtc_time *tm, time64_t *time)
>
> What's the point of the return value? Just because rtc_tm_to_time()
> has one?
>
> Yes it does, but that does not mean that we blindly copy the existing
> nonsense when we implement a replacement interface.
>
> What's wrong with changing it to:
>
> time64_t rtc_tm_to_time64(struct rtc_time *tm)
> {
> return mktime64(......);
> }
Thank you for reminding me of this, and also a valuable principle when
doing things.
I wanna change it to:
void rtc_tm_to_time64(struct rtc_time *tm, time64_t *time)
{
time = mktime64(......);
}
Just keep it the similar format as rtc_time64_to_tm(), is this acceptable?
>
>> +/*
>> + * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
>> + * TODO: [2038 safety] should be replaced by rtc_tm_to_time64.
>
> Groan.
>
>> */
>> int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
>> {
>> - *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
>> + *time = (unsigned long) mktime64(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
>> tm->tm_hour, tm->tm_min, tm->tm_sec);
>
> And that would become
>
> *time = rtc_time_to_time64(tm);
>
>> return 0;
>> }
>
> Please stop doing purely mechanical changes. Just blindly copying
> stuff and make it take time64_t instead of unsigned long can be done
> with a script as well.
>
> Thanks,
>
> tglx
On Fri, 31 Oct 2014, pang.xunlei wrote:
> On 30 October 2014 21:55, Thomas Gleixner <[email protected]> wrote:
> > What's wrong with changing it to:
> >
> > time64_t rtc_tm_to_time64(struct rtc_time *tm)
> > {
> > return mktime64(......);
> > }
>
> Thank you for reminding me of this, and also a valuable principle when
> doing things.
>
> I wanna change it to:
> void rtc_tm_to_time64(struct rtc_time *tm, time64_t *time)
> {
> time = mktime64(......);
> }
>
> Just keep it the similar format as rtc_time64_to_tm(), is this acceptable?
Why on earth want you do that? Just because it looks the same or what?
Come on, it's not that hard and this is not the CS 'Java for dummies'
course where you get an A for implementing 'looks the same' nonsense.
For rtc_time64_to_tm() you really want to hand in the pointer for the
result because returning the full structure is overkill as it involves
heavy stack operations.
But for rtc_tm_to_time64() this is a different story. All relevant
32bit architectures can deal with a u64 return value very well and in
most cases it creates better code.
Just do the simple experiment of implementing both, converting a dozen
drivers and comparing the resulting assembler code on the call sites
and the function itself. That should give you an objective decision
criteria instead of "wanna change just because I feel it looks better".
Another valuable principle of doing things to remember, right?
Thanks,
tglx