Commit c2c11ae4b6bc03b41720337028b940cbec9e316f
Committed by
John Stultz
1 parent
5322e4c264
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
rtc/lib: Provide y2038 safe rtc_tm_to_time()/rtc_time_to_tm() replacement
As part of addressing "y2038 problem" for in-kernel uses, this patch adds safe rtc_tm_to_time64()/rtc_time64_to_tm() respectively using time64_t. After this patch, rtc_tm_to_time() is deprecated and all its call sites will be fixed using corresponding safe versions, it can be removed when having no users. Also change rtc_tm_to_time64() to return time64_t directly instead of just as a parameter like rtc_tm_to_time() does. After this patch, rtc_time_to_tm() is deprecated and all its call sites will be fixed using corresponding safe versions, it can be removed when having no users. In addition, change rtc_tm_to_ktime() and rtc_ktime_to_tm() to use the safe version in passing. Signed-off-by: pang.xunlei <pang.xunlei@linaro.org> Signed-off-by: John Stultz <john.stultz@linaro.org>
Showing 2 changed files with 39 additions and 20 deletions Side-by-side Diff
drivers/rtc/rtc-lib.c
... | ... | @@ -45,16 +45,20 @@ |
45 | 45 | } |
46 | 46 | EXPORT_SYMBOL(rtc_year_days); |
47 | 47 | |
48 | + | |
48 | 49 | /* |
50 | + * rtc_time_to_tm64 - Converts time64_t to rtc_time. | |
49 | 51 | * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. |
50 | 52 | */ |
51 | -void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) | |
53 | +void rtc_time64_to_tm(time64_t time, struct rtc_time *tm) | |
52 | 54 | { |
53 | 55 | unsigned int month, year; |
56 | + unsigned long secs; | |
54 | 57 | int days; |
55 | 58 | |
56 | - days = time / 86400; | |
57 | - time -= (unsigned int) days * 86400; | |
59 | + /* time must be positive */ | |
60 | + days = div_s64(time, 86400); | |
61 | + secs = time - (unsigned int) days * 86400; | |
58 | 62 | |
59 | 63 | /* day of the week, 1970-01-01 was a Thursday */ |
60 | 64 | tm->tm_wday = (days + 4) % 7; |
61 | 65 | |
... | ... | @@ -81,14 +85,14 @@ |
81 | 85 | tm->tm_mon = month; |
82 | 86 | tm->tm_mday = days + 1; |
83 | 87 | |
84 | - tm->tm_hour = time / 3600; | |
85 | - time -= tm->tm_hour * 3600; | |
86 | - tm->tm_min = time / 60; | |
87 | - tm->tm_sec = time - tm->tm_min * 60; | |
88 | + tm->tm_hour = secs / 3600; | |
89 | + secs -= tm->tm_hour * 3600; | |
90 | + tm->tm_min = secs / 60; | |
91 | + tm->tm_sec = secs - tm->tm_min * 60; | |
88 | 92 | |
89 | 93 | tm->tm_isdst = 0; |
90 | 94 | } |
91 | -EXPORT_SYMBOL(rtc_time_to_tm); | |
95 | +EXPORT_SYMBOL(rtc_time64_to_tm); | |
92 | 96 | |
93 | 97 | /* |
94 | 98 | * Does the rtc_time represent a valid date/time? |
95 | 99 | |
96 | 100 | |
97 | 101 | |
98 | 102 | |
99 | 103 | |
... | ... | @@ -109,24 +113,22 @@ |
109 | 113 | EXPORT_SYMBOL(rtc_valid_tm); |
110 | 114 | |
111 | 115 | /* |
116 | + * rtc_tm_to_time64 - Converts rtc_time to time64_t. | |
112 | 117 | * Convert Gregorian date to seconds since 01-01-1970 00:00:00. |
113 | 118 | */ |
114 | -int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) | |
119 | +time64_t rtc_tm_to_time64(struct rtc_time *tm) | |
115 | 120 | { |
116 | - *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, | |
121 | + return mktime64(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, | |
117 | 122 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
118 | - return 0; | |
119 | 123 | } |
120 | -EXPORT_SYMBOL(rtc_tm_to_time); | |
124 | +EXPORT_SYMBOL(rtc_tm_to_time64); | |
121 | 125 | |
122 | 126 | /* |
123 | 127 | * Convert rtc_time to ktime |
124 | 128 | */ |
125 | 129 | ktime_t rtc_tm_to_ktime(struct rtc_time tm) |
126 | 130 | { |
127 | - time_t time; | |
128 | - rtc_tm_to_time(&tm, &time); | |
129 | - return ktime_set(time, 0); | |
131 | + return ktime_set(rtc_tm_to_time64(&tm), 0); | |
130 | 132 | } |
131 | 133 | EXPORT_SYMBOL_GPL(rtc_tm_to_ktime); |
132 | 134 | |
133 | 135 | |
134 | 136 | |
... | ... | @@ -135,14 +137,14 @@ |
135 | 137 | */ |
136 | 138 | struct rtc_time rtc_ktime_to_tm(ktime_t kt) |
137 | 139 | { |
138 | - struct timespec ts; | |
140 | + struct timespec64 ts; | |
139 | 141 | struct rtc_time ret; |
140 | 142 | |
141 | - ts = ktime_to_timespec(kt); | |
143 | + ts = ktime_to_timespec64(kt); | |
142 | 144 | /* Round up any ns */ |
143 | 145 | if (ts.tv_nsec) |
144 | 146 | ts.tv_sec++; |
145 | - rtc_time_to_tm(ts.tv_sec, &ret); | |
147 | + rtc_time64_to_tm(ts.tv_sec, &ret); | |
146 | 148 | return ret; |
147 | 149 | } |
148 | 150 | EXPORT_SYMBOL_GPL(rtc_ktime_to_tm); |
include/linux/rtc.h
... | ... | @@ -19,11 +19,28 @@ |
19 | 19 | extern int rtc_month_days(unsigned int month, unsigned int year); |
20 | 20 | extern int rtc_year_days(unsigned int day, unsigned int month, unsigned int year); |
21 | 21 | extern int rtc_valid_tm(struct rtc_time *tm); |
22 | -extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time); | |
23 | -extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm); | |
22 | +extern time64_t rtc_tm_to_time64(struct rtc_time *tm); | |
23 | +extern void rtc_time64_to_tm(time64_t time, struct rtc_time *tm); | |
24 | 24 | ktime_t rtc_tm_to_ktime(struct rtc_time tm); |
25 | 25 | struct rtc_time rtc_ktime_to_tm(ktime_t kt); |
26 | 26 | |
27 | +/** | |
28 | + * Deprecated. Use rtc_time64_to_tm(). | |
29 | + */ | |
30 | +static inline void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) | |
31 | +{ | |
32 | + rtc_time64_to_tm(time, tm); | |
33 | +} | |
34 | + | |
35 | +/** | |
36 | + * Deprecated. Use rtc_tm_to_time64(). | |
37 | + */ | |
38 | +static inline int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) | |
39 | +{ | |
40 | + *time = rtc_tm_to_time64(tm); | |
41 | + | |
42 | + return 0; | |
43 | +} | |
27 | 44 | |
28 | 45 | #include <linux/device.h> |
29 | 46 | #include <linux/seq_file.h> |