Message ID | 20241009-devel-anna-maria-b4-timers-ptp-timekeeping-v2-17-554456a44a15@linutronix.de (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
Series | timekeeping: Rework to prepare support of indenpendent PTP clocks | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Not a local patch |
On Wed, Oct 9, 2024 at 1:29 AM Anna-Maria Behnsen <anna-maria@linutronix.de> wrote: > > From: Anna-Maria Behnsen <anna-maria@linutronix.de> > > Updates of the timekeeper can be done by operating on the shadow timekeeper > and afterwards copying the result into the real timekeeper. This has the > advantage, that the sequence count write protected region is kept as small > as possible. > > Convert timekeeping_inject_offset() to use this scheme. > > That allows to use a scoped_guard() for locking the timekeeper lock as the > usage of the shadow timekeeper allows a rollback in the error case instead > of the full timekeeper update of the original code. > > Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de> > --- > kernel/time/timekeeping.c | 41 ++++++++++++++++------------------------- > 1 file changed, 16 insertions(+), 25 deletions(-) > > diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c > index cc01ad53d96d..051041e92e54 100644 > --- a/kernel/time/timekeeping.c > +++ b/kernel/time/timekeeping.c > @@ -1519,40 +1519,31 @@ EXPORT_SYMBOL(do_settimeofday64); > */ > static int timekeeping_inject_offset(const struct timespec64 *ts) > { > - struct timekeeper *tk = &tk_core.timekeeper; > - unsigned long flags; > - struct timespec64 tmp; > - int ret = 0; > - > if (ts->tv_nsec < 0 || ts->tv_nsec >= NSEC_PER_SEC) > return -EINVAL; > > - raw_spin_lock_irqsave(&tk_core.lock, flags); > - write_seqcount_begin(&tk_core.seq); > - > - timekeeping_forward_now(tk); > - > - /* Make sure the proposed value is valid */ > - tmp = timespec64_add(tk_xtime(tk), *ts); > - if (timespec64_compare(&tk->wall_to_monotonic, ts) > 0 || > - !timespec64_valid_settod(&tmp)) { > - ret = -EINVAL; > - goto error; > - } > + scoped_guard (raw_spinlock_irqsave, &tk_core.lock) { > + struct timekeeper *tk = &tk_core.shadow_timekeeper; Nit: Same suggestion of naming this tk_shadow for added clarity. Otherwise, Acked-by: John Stultz <jstultz@google.com>
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index cc01ad53d96d..051041e92e54 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1519,40 +1519,31 @@ EXPORT_SYMBOL(do_settimeofday64); */ static int timekeeping_inject_offset(const struct timespec64 *ts) { - struct timekeeper *tk = &tk_core.timekeeper; - unsigned long flags; - struct timespec64 tmp; - int ret = 0; - if (ts->tv_nsec < 0 || ts->tv_nsec >= NSEC_PER_SEC) return -EINVAL; - raw_spin_lock_irqsave(&tk_core.lock, flags); - write_seqcount_begin(&tk_core.seq); - - timekeeping_forward_now(tk); - - /* Make sure the proposed value is valid */ - tmp = timespec64_add(tk_xtime(tk), *ts); - if (timespec64_compare(&tk->wall_to_monotonic, ts) > 0 || - !timespec64_valid_settod(&tmp)) { - ret = -EINVAL; - goto error; - } + scoped_guard (raw_spinlock_irqsave, &tk_core.lock) { + struct timekeeper *tk = &tk_core.shadow_timekeeper; + struct timespec64 tmp; - tk_xtime_add(tk, ts); - tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, *ts)); + timekeeping_forward_now(tk); -error: /* even if we error out, we forwarded the time, so call update */ - timekeeping_update(&tk_core, tk, TK_UPDATE_ALL | TK_MIRROR); + /* Make sure the proposed value is valid */ + tmp = timespec64_add(tk_xtime(tk), *ts); + if (timespec64_compare(&tk->wall_to_monotonic, ts) > 0 || + !timespec64_valid_settod(&tmp)) { + timekeeping_restore_shadow(&tk_core); + return -EINVAL; + } - write_seqcount_end(&tk_core.seq); - raw_spin_unlock_irqrestore(&tk_core.lock, flags); + tk_xtime_add(tk, ts); + tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, *ts)); + timekeeping_update_staged(&tk_core, TK_UPDATE_ALL); + } /* Signal hrtimers about time change */ clock_was_set(CLOCK_SET_WALL); - - return ret; + return 0; } /*