diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-07 13:37:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-07 13:37:48 -0400 |
commit | ebc54f278f496798a3ea1df9ae29c1055e9de95e (patch) | |
tree | bdcd1fa48c0e318a203ca1c4c048e1855cc81ec7 /kernel | |
parent | 2b12164b55e76e421c069de2cdf6b04c077983f1 (diff) | |
parent | 9bf2419fa7bffa16ce58a4d5c20399eff8c970c9 (diff) |
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer fixes from Thomas Gleixner:
"Three fixlets from the timer departement:
- Update the timekeeper before updating vsyscall and pvclock. This
fixes the kvm-clock regression reported by Chris and Paolo.
- Use the proper irq work interface from NMI. This fixes the
regression reported by Catalin and Dave.
- Clarify the compat_nanosleep error handling mechanism to avoid
future confusion"
* 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
timekeeping: Update timekeeper before updating vsyscall and pvclock
compat: nanosleep: Clarify error handling
nohz: Restore NMI safe local irq work for local nohz kick
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/compat.c | 24 | ||||
-rw-r--r-- | kernel/time/tick-sched.c | 14 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 5 |
3 files changed, 38 insertions, 5 deletions
diff --git a/kernel/compat.c b/kernel/compat.c index 633394f442f8..ebb3c369d03d 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -226,7 +226,7 @@ static long compat_nanosleep_restart(struct restart_block *restart) | |||
226 | ret = hrtimer_nanosleep_restart(restart); | 226 | ret = hrtimer_nanosleep_restart(restart); |
227 | set_fs(oldfs); | 227 | set_fs(oldfs); |
228 | 228 | ||
229 | if (ret) { | 229 | if (ret == -ERESTART_RESTARTBLOCK) { |
230 | rmtp = restart->nanosleep.compat_rmtp; | 230 | rmtp = restart->nanosleep.compat_rmtp; |
231 | 231 | ||
232 | if (rmtp && compat_put_timespec(&rmt, rmtp)) | 232 | if (rmtp && compat_put_timespec(&rmt, rmtp)) |
@@ -256,7 +256,26 @@ COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp, | |||
256 | HRTIMER_MODE_REL, CLOCK_MONOTONIC); | 256 | HRTIMER_MODE_REL, CLOCK_MONOTONIC); |
257 | set_fs(oldfs); | 257 | set_fs(oldfs); |
258 | 258 | ||
259 | if (ret) { | 259 | /* |
260 | * hrtimer_nanosleep() can only return 0 or | ||
261 | * -ERESTART_RESTARTBLOCK here because: | ||
262 | * | ||
263 | * - we call it with HRTIMER_MODE_REL and therefor exclude the | ||
264 | * -ERESTARTNOHAND return path. | ||
265 | * | ||
266 | * - we supply the rmtp argument from the task stack (due to | ||
267 | * the necessary compat conversion. So the update cannot | ||
268 | * fail, which excludes the -EFAULT return path as well. If | ||
269 | * it fails nevertheless we have a bigger problem and wont | ||
270 | * reach this place anymore. | ||
271 | * | ||
272 | * - if the return value is 0, we do not have to update rmtp | ||
273 | * because there is no remaining time. | ||
274 | * | ||
275 | * We check for -ERESTART_RESTARTBLOCK nevertheless if the | ||
276 | * core implementation decides to return random nonsense. | ||
277 | */ | ||
278 | if (ret == -ERESTART_RESTARTBLOCK) { | ||
260 | struct restart_block *restart | 279 | struct restart_block *restart |
261 | = ¤t_thread_info()->restart_block; | 280 | = ¤t_thread_info()->restart_block; |
262 | 281 | ||
@@ -266,7 +285,6 @@ COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp, | |||
266 | if (rmtp && compat_put_timespec(&rmt, rmtp)) | 285 | if (rmtp && compat_put_timespec(&rmt, rmtp)) |
267 | return -EFAULT; | 286 | return -EFAULT; |
268 | } | 287 | } |
269 | |||
270 | return ret; | 288 | return ret; |
271 | } | 289 | } |
272 | 290 | ||
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 99aa6ee3908f..f654a8a298fa 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -225,6 +225,20 @@ static DEFINE_PER_CPU(struct irq_work, nohz_full_kick_work) = { | |||
225 | }; | 225 | }; |
226 | 226 | ||
227 | /* | 227 | /* |
228 | * Kick this CPU if it's full dynticks in order to force it to | ||
229 | * re-evaluate its dependency on the tick and restart it if necessary. | ||
230 | * This kick, unlike tick_nohz_full_kick_cpu() and tick_nohz_full_kick_all(), | ||
231 | * is NMI safe. | ||
232 | */ | ||
233 | void tick_nohz_full_kick(void) | ||
234 | { | ||
235 | if (!tick_nohz_full_cpu(smp_processor_id())) | ||
236 | return; | ||
237 | |||
238 | irq_work_queue(&__get_cpu_var(nohz_full_kick_work)); | ||
239 | } | ||
240 | |||
241 | /* | ||
228 | * Kick the CPU if it's full dynticks in order to force it to | 242 | * Kick the CPU if it's full dynticks in order to force it to |
229 | * re-evaluate its dependency on the tick and restart it if necessary. | 243 | * re-evaluate its dependency on the tick and restart it if necessary. |
230 | */ | 244 | */ |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index fb4a9c2cf8d9..ec1791fae965 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -442,11 +442,12 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action) | |||
442 | tk->ntp_error = 0; | 442 | tk->ntp_error = 0; |
443 | ntp_clear(); | 443 | ntp_clear(); |
444 | } | 444 | } |
445 | update_vsyscall(tk); | ||
446 | update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET); | ||
447 | 445 | ||
448 | tk_update_ktime_data(tk); | 446 | tk_update_ktime_data(tk); |
449 | 447 | ||
448 | update_vsyscall(tk); | ||
449 | update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET); | ||
450 | |||
450 | if (action & TK_MIRROR) | 451 | if (action & TK_MIRROR) |
451 | memcpy(&shadow_timekeeper, &tk_core.timekeeper, | 452 | memcpy(&shadow_timekeeper, &tk_core.timekeeper, |
452 | sizeof(tk_core.timekeeper)); | 453 | sizeof(tk_core.timekeeper)); |