diff options
author | Kees Cook <keescook@chromium.org> | 2012-11-19 19:26:16 +0100 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2013-01-16 03:16:02 +0100 |
commit | 1e817fb62cd185a2232ad4302579491805609489 (patch) | |
tree | d4155fb65a9fb32cd9236405a8b7534f39c293b9 /kernel/time | |
parent | Merge branch 'fortglx/3.8/time' of git://git.linaro.org/people/jstultz/linux ... (diff) | |
download | linux-1e817fb62cd185a2232ad4302579491805609489.tar.xz linux-1e817fb62cd185a2232ad4302579491805609489.zip |
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')
-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) } /** - * getnstimeofday - Returns the time of day in a timespec + * __getnstimeofday - Returns the time of day in a timespec. * @ts: pointer to the timespec to be set * - * Returns the time of day in a timespec. + * Updates the time of day in the timespec. + * Returns 0 on success, or -ve when suspended (timespec will be undefined). */ -void getnstimeofday(struct timespec *ts) +int __getnstimeofday(struct timespec *ts) { struct timekeeper *tk = &timekeeper; unsigned long seq; s64 nsecs = 0; - WARN_ON(timekeeping_suspended); - do { seq = read_seqbegin(&tk->lock); @@ -237,6 +236,26 @@ void getnstimeofday(struct timespec *ts) ts->tv_nsec = 0; timespec_add_ns(ts, nsecs); + + /* + * Do not bail out early, in case there were callers still using + * the value, even in the face of the WARN_ON. + */ + if (unlikely(timekeeping_suspended)) + return -EAGAIN; + return 0; +} +EXPORT_SYMBOL(__getnstimeofday); + +/** + * getnstimeofday - Returns the time of day in a timespec. + * @ts: pointer to the timespec to be set + * + * Returns the time of day in a timespec (WARN if suspended). + */ +void getnstimeofday(struct timespec *ts) +{ + WARN_ON(__getnstimeofday(ts)); } EXPORT_SYMBOL(getnstimeofday); |