aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/timekeeping.c
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2012-11-19 13:26:16 -0500
committerJohn Stultz <john.stultz@linaro.org>2013-01-15 21:16:02 -0500
commit1e817fb62cd185a2232ad4302579491805609489 (patch)
treed4155fb65a9fb32cd9236405a8b7534f39c293b9 /kernel/time/timekeeping.c
parent9c3f9e281697d02889c3b08922f3b30be75f56c2 (diff)
time: create __getnstimeofday for WARNless calls
The pstore RAM backend can get called during resume, and must be defensive against a suspended time source. Expose getnstimeofday logic that returns an error instead of a WARN. This can be detected and the timestamp can be zeroed out. Reported-by: Doug Anderson <dianders@chromium.org> Cc: John Stultz <johnstul@us.ibm.com> Cc: Anton Vorontsov <anton.vorontsov@linaro.org> Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'kernel/time/timekeeping.c')
-rw-r--r--kernel/time/timekeeping.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 4c7de02eacdc..dfc7f87eb332 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -214,19 +214,18 @@ static void timekeeping_forward_now(struct timekeeper *tk)
214} 214}
215 215
216/** 216/**
217 * getnstimeofday - Returns the time of day in a timespec 217 * __getnstimeofday - Returns the time of day in a timespec.
218 * @ts: pointer to the timespec to be set 218 * @ts: pointer to the timespec to be set
219 * 219 *
220 * Returns the time of day in a timespec. 220 * Updates the time of day in the timespec.
221 * Returns 0 on success, or -ve when suspended (timespec will be undefined).
221 */ 222 */
222void getnstimeofday(struct timespec *ts) 223int __getnstimeofday(struct timespec *ts)
223{ 224{
224 struct timekeeper *tk = &timekeeper; 225 struct timekeeper *tk = &timekeeper;
225 unsigned long seq; 226 unsigned long seq;
226 s64 nsecs = 0; 227 s64 nsecs = 0;
227 228
228 WARN_ON(timekeeping_suspended);
229
230 do { 229 do {
231 seq = read_seqbegin(&tk->lock); 230 seq = read_seqbegin(&tk->lock);
232 231
@@ -237,6 +236,26 @@ void getnstimeofday(struct timespec *ts)
237 236
238 ts->tv_nsec = 0; 237 ts->tv_nsec = 0;
239 timespec_add_ns(ts, nsecs); 238 timespec_add_ns(ts, nsecs);
239
240 /*
241 * Do not bail out early, in case there were callers still using
242 * the value, even in the face of the WARN_ON.
243 */
244 if (unlikely(timekeeping_suspended))
245 return -EAGAIN;
246 return 0;
247}
248EXPORT_SYMBOL(__getnstimeofday);
249
250/**
251 * getnstimeofday - Returns the time of day in a timespec.
252 * @ts: pointer to the timespec to be set
253 *
254 * Returns the time of day in a timespec (WARN if suspended).
255 */
256void getnstimeofday(struct timespec *ts)
257{
258 WARN_ON(__getnstimeofday(ts));
240} 259}
241EXPORT_SYMBOL(getnstimeofday); 260EXPORT_SYMBOL(getnstimeofday);
242 261