diff options
author | Kees Cook <keescook@chromium.org> | 2012-11-19 13:26:16 -0500 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2013-01-15 21:16:02 -0500 |
commit | 1e817fb62cd185a2232ad4302579491805609489 (patch) | |
tree | d4155fb65a9fb32cd9236405a8b7534f39c293b9 /kernel/time/timekeeping.c | |
parent | 9c3f9e281697d02889c3b08922f3b30be75f56c2 (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.c | 29 |
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 | */ |
222 | void getnstimeofday(struct timespec *ts) | 223 | int __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 | } | ||
248 | EXPORT_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 | */ | ||
256 | void getnstimeofday(struct timespec *ts) | ||
257 | { | ||
258 | WARN_ON(__getnstimeofday(ts)); | ||
240 | } | 259 | } |
241 | EXPORT_SYMBOL(getnstimeofday); | 260 | EXPORT_SYMBOL(getnstimeofday); |
242 | 261 | ||