On Mon, Jan 30, 2023 at 03:39:45PM +, Wojtek Wasko via Linuxptp-devel wrote:
> Current code only prints a message in case the kernel returns an error
> for a clock adjustment. Failing to adjust clock leads to an inconsistent
> state in which a servo continues to report "locked" state while the
> underlying PHC's state is essentially undetermined.
>
> This change resets the servo in case of failure to adjust the clock.
I like the error handling, but I'd like to have this one patch split
into a series of four patches:
1. Let methods in clockadj.[ch] return errors to caller.
2. Implement error handling in ptp4l.
3. Implement error handling in phc2sys.
4. Implement error handling in ts2phc.
That way, in the unlikely event of a regression, we can revert 2, 3, or 4.
Also, I have a few minor comments on coding style...
> diff --git a/clock.c b/clock.c
> index 134c7c3..ff1abbf 100644
> --- a/clock.c
> +++ b/clock.c
> @@ -1778,18 +1778,20 @@ static void clock_step_window(struct clock *c)
> c->step_window_counter = c->step_window;
> }
>
> -static void clock_synchronize_locked(struct clock *c, double adj)
> +static int clock_synchronize_locked(struct clock *c, double adj)
> {
> if (c->sanity_check) {
> clockcheck_freq(c->sanity_check, clockadj_get_freq(c->clkid));
> }
> - clockadj_set_freq(c->clkid, -adj);
> + if (clockadj_set_freq(c->clkid, -adj) < 0)
> + return -1;
Please don't omit the braces, and drop the '< 0'
clockadj_set_freq returns either 0 or -1, so the test should be
simplified to 'if (clockadj_set_freq()) { ... }'
> if (c->clkid == CLOCK_REALTIME) {
> sysclk_set_sync();
> }
> if (c->sanity_check) {
> clockcheck_set_freq(c->sanity_check, -adj);
> }
> + return 0;
> }
>
> enum servo_state clock_synchronize(struct clock *c, tmv_t ingress, tmv_t
> origin)
> @@ -1841,8 +1843,10 @@ enum servo_state clock_synchronize(struct clock *c,
> tmv_t ingress, tmv_t origin)
> case SERVO_UNLOCKED:
> break;
> case SERVO_JUMP:
> - clockadj_set_freq(c->clkid, -adj);
> - clockadj_step(c->clkid, -tmv_to_nanoseconds(c->master_offset));
> + if (clockadj_set_freq(c->clkid, -adj) < 0)
> + goto servo_unlock;
Same here
> + if (clockadj_step(c->clkid,
> -tmv_to_nanoseconds(c->master_offset)) < 0)
> + goto servo_unlock;
and here
> c->ingress_ts = tmv_zero();
> if (c->sanity_check) {
> clockcheck_set_freq(c->sanity_check, -adj);
> @@ -1853,14 +1857,17 @@ enum servo_state clock_synchronize(struct clock *c,
> tmv_t ingress, tmv_t origin)
> clock_step_window(c);
> break;
> case SERVO_LOCKED:
> - clock_synchronize_locked(c, adj);
> + if (clock_synchronize_locked(c, adj) < 0)
> + goto servo_unlock;
ditto
> break;
> case SERVO_LOCKED_STABLE:
> if (c->write_phase_mode) {
> - clockadj_set_phase(c->clkid, -offset);
> + if (clockadj_set_phase(c->clkid, -offset) < 0)
> + goto servo_unlock;
ditto
> adj = 0;
> } else {
> - clock_synchronize_locked(c, adj);
> + if (clock_synchronize_locked(c, adj) < 0)
> + goto servo_unlock;
ditto
> }
> break;
> }
> @@ -1877,6 +1884,11 @@ enum servo_state clock_synchronize(struct clock *c,
> tmv_t ingress, tmv_t origin)
> clock_notify_event(c, NOTIFY_TIME_SYNC);
>
> return state;
> +
> +servo_unlock:
> + servo_reset(c->servo);
> + c->servo_state = SERVO_UNLOCKED;
> + return SERVO_UNLOCKED;
> }
>
> void clock_sync_interval(struct clock *c, int n)
> diff --git a/clockadj.c b/clockadj.c
> index 4c920b9..1437ec0 100644
> --- a/clockadj.c
> +++ b/clockadj.c
> @@ -48,7 +48,7 @@ void clockadj_init(clockid_t clkid)
> #endif
> }
>
> -void clockadj_set_freq(clockid_t clkid, double freq)
> +int clockadj_set_freq(clockid_t clkid, double freq)
> {
> struct timex tx;
> memset(&tx, 0, sizeof(tx));
> @@ -62,8 +62,11 @@ void clockadj_set_freq(clockid_t clkid, double freq)
>
> tx.modes |= ADJ_FREQUENCY;
> tx.freq = (long) (freq * 65.536);
> - if (clock_adjtime(clkid, &tx) < 0)
> + if (clock_adjtime(clkid, &tx) < 0) {
FYI here the '< 0" makes sense, because clock_adjtime is the cousin of
adjtimex which can return both -1 and positive time code.
> pr_err("failed to adjust the clock: %m");
> + return -1;
> + }
> + return 0;
> }
>
> double clockadj_get_freq(clockid_t clkid)
Thanks,
Richard
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.