@@ -3079,12 +3079,13 @@ static int method_endpoint_remove(sd_bus_message *call, void *data,
30793079 (MCTP_I2C_TSYM_MT1_MAX_US + 2 * MCTP_I2C_TSYM_MT3_MAX_US)
30803080#define MCTP_I2C_TSYM_MT2_MAX_MS MCTP_I2C_TSYM_MT4_MIN_US
30813081
3082- static int peer_endpoint_recover (sd_event_source * s , uint64_t usec ,
3082+ static int peer_endpoint_recover (sd_event_source * s , int timerfd , uint revents ,
30833083 void * userdata )
30843084{
30853085 struct peer * peer = userdata ;
30863086 struct ctx * ctx = peer -> ctx ;
30873087 const char * peer_path ;
3088+ uint64_t n_expireds ;
30883089 int rc ;
30893090
30903091 /*
@@ -3099,6 +3100,12 @@ static int peer_endpoint_recover(sd_event_source *s, uint64_t usec,
30993100
31003101 peer -> recovery .npolls -- ;
31013102
3103+ // flush the timerfd
3104+ rc = mctp_ops .timerfd .read (timerfd , & n_expireds );
3105+ if (rc < 0 ) {
3106+ goto reschedule ;
3107+ }
3108+
31023109 /*
31033110 * Test if we still have connectivity to the endpoint. If we do, we will get a
31043111 * response reporting the current EID. This is the test recommended by 8.17.6
@@ -3194,8 +3201,7 @@ static int peer_endpoint_recover(sd_event_source *s, uint64_t usec,
31943201
31953202reschedule :
31963203 if (peer -> recovery .npolls > 0 ) {
3197- rc = sd_event_source_set_time_relative (peer -> recovery .source ,
3198- peer -> recovery .delay );
3204+ rc = mctp_ops .timerfd .settime (timerfd , peer -> recovery .delay , NULL );
31993205 if (rc >= 0 ) {
32003206 rc = sd_event_source_set_enabled (peer -> recovery .source ,
32013207 SD_EVENT_ONESHOT );
@@ -3217,11 +3223,13 @@ static int method_endpoint_recover(sd_bus_message *call, void *data,
32173223 struct peer * peer ;
32183224 bool previously ;
32193225 struct ctx * ctx ;
3226+ int timerfd ;
32203227 int rc ;
32213228
32223229 peer = data ;
32233230 ctx = peer -> ctx ;
32243231 previously = peer -> degraded ;
3232+ timerfd = -1 ;
32253233
32263234 if (!previously ) {
32273235 assert (!peer -> recovery .delay );
@@ -3230,13 +3238,38 @@ static int method_endpoint_recover(sd_bus_message *call, void *data,
32303238 peer -> recovery .npolls = MCTP_I2C_TSYM_MN1_MIN + 1 ;
32313239 peer -> recovery .delay =
32323240 (MCTP_I2C_TSYM_TRECLAIM_MIN_US / 2 ) - ctx -> mctp_timeout ;
3233- rc = sd_event_add_time_relative (
3234- ctx -> event , & peer -> recovery .source , CLOCK_MONOTONIC , 0 ,
3235- ctx -> mctp_timeout , peer_endpoint_recover , peer );
3241+
3242+ timerfd = mctp_ops .timerfd .create ();
3243+ if (timerfd < 0 ) {
3244+ rc = - errno ;
3245+ goto out ;
3246+ }
3247+
3248+ rc = mctp_ops .timerfd .settime (timerfd , ctx -> mctp_timeout , NULL );
3249+ if (rc < 0 ) {
3250+ goto out ;
3251+ }
3252+
3253+ rc = sd_event_add_io (ctx -> event , & peer -> recovery .source ,
3254+ timerfd , EPOLLIN , peer_endpoint_recover ,
3255+ peer );
3256+ if (rc < 0 ) {
3257+ goto out ;
3258+ }
3259+
3260+ rc = sd_event_source_set_enabled (peer -> recovery .source ,
3261+ SD_EVENT_ONESHOT );
32363262 if (rc < 0 ) {
32373263 goto out ;
32383264 }
32393265
3266+ rc = sd_event_source_set_io_fd_own (peer -> recovery .source , true);
3267+ if (rc < 0 ) {
3268+ goto out ;
3269+ }
3270+ // prevent double close, now that sd_event_source own the fd
3271+ timerfd = -1 ;
3272+
32403273 peer -> degraded = true;
32413274
32423275 rc = sd_bus_emit_properties_changed (
@@ -3253,12 +3286,8 @@ static int method_endpoint_recover(sd_bus_message *call, void *data,
32533286
32543287out :
32553288 if (rc < 0 && !previously ) {
3256- if (peer -> degraded ) {
3257- /* Cleanup the timer if it was setup successfully. */
3258- sd_event_source_set_enabled (peer -> recovery .source ,
3259- SD_EVENT_OFF );
3260- sd_event_source_unref (peer -> recovery .source );
3261- }
3289+ sd_event_source_disable_unref (peer -> recovery .source );
3290+ close (timerfd );
32623291 peer -> degraded = previously ;
32633292 peer -> recovery .delay = 0 ;
32643293 peer -> recovery .source = NULL ;
0 commit comments