@@ -32,7 +32,7 @@ static ktime_t gate_get_time(struct tcf_gate *gact)
32
32
return KTIME_MAX ;
33
33
}
34
34
35
- static int gate_get_start_time (struct tcf_gate * gact , ktime_t * start )
35
+ static void gate_get_start_time (struct tcf_gate * gact , ktime_t * start )
36
36
{
37
37
struct tcf_gate_params * param = & gact -> param ;
38
38
ktime_t now , base , cycle ;
@@ -43,18 +43,13 @@ static int gate_get_start_time(struct tcf_gate *gact, ktime_t *start)
43
43
44
44
if (ktime_after (base , now )) {
45
45
* start = base ;
46
- return 0 ;
46
+ return ;
47
47
}
48
48
49
49
cycle = param -> tcfg_cycletime ;
50
50
51
- /* cycle time should not be zero */
52
- if (!cycle )
53
- return - EFAULT ;
54
-
55
51
n = div64_u64 (ktime_sub_ns (now , base ), cycle );
56
52
* start = ktime_add_ns (base , (n + 1 ) * cycle );
57
- return 0 ;
58
53
}
59
54
60
55
static void gate_start_timer (struct tcf_gate * gact , ktime_t start )
@@ -277,6 +272,27 @@ static int parse_gate_list(struct nlattr *list_attr,
277
272
return err ;
278
273
}
279
274
275
+ static void gate_setup_timer (struct tcf_gate * gact , u64 basetime ,
276
+ enum tk_offsets tko , s32 clockid ,
277
+ bool do_init )
278
+ {
279
+ if (!do_init ) {
280
+ if (basetime == gact -> param .tcfg_basetime &&
281
+ tko == gact -> tk_offset &&
282
+ clockid == gact -> param .tcfg_clockid )
283
+ return ;
284
+
285
+ spin_unlock_bh (& gact -> tcf_lock );
286
+ hrtimer_cancel (& gact -> hitimer );
287
+ spin_lock_bh (& gact -> tcf_lock );
288
+ }
289
+ gact -> param .tcfg_basetime = basetime ;
290
+ gact -> param .tcfg_clockid = clockid ;
291
+ gact -> tk_offset = tko ;
292
+ hrtimer_init (& gact -> hitimer , clockid , HRTIMER_MODE_ABS_SOFT );
293
+ gact -> hitimer .function = gate_timer_func ;
294
+ }
295
+
280
296
static int tcf_gate_init (struct net * net , struct nlattr * nla ,
281
297
struct nlattr * est , struct tc_action * * a ,
282
298
int ovr , int bind , bool rtnl_held ,
@@ -287,12 +303,12 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
287
303
enum tk_offsets tk_offset = TK_OFFS_TAI ;
288
304
struct nlattr * tb [TCA_GATE_MAX + 1 ];
289
305
struct tcf_chain * goto_ch = NULL ;
306
+ u64 cycletime = 0 , basetime = 0 ;
290
307
struct tcf_gate_params * p ;
291
308
s32 clockid = CLOCK_TAI ;
292
309
struct tcf_gate * gact ;
293
310
struct tc_gate * parm ;
294
311
int ret = 0 , err ;
295
- u64 basetime = 0 ;
296
312
u32 gflags = 0 ;
297
313
s32 prio = -1 ;
298
314
ktime_t start ;
@@ -308,6 +324,27 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
308
324
if (!tb [TCA_GATE_PARMS ])
309
325
return - EINVAL ;
310
326
327
+ if (tb [TCA_GATE_CLOCKID ]) {
328
+ clockid = nla_get_s32 (tb [TCA_GATE_CLOCKID ]);
329
+ switch (clockid ) {
330
+ case CLOCK_REALTIME :
331
+ tk_offset = TK_OFFS_REAL ;
332
+ break ;
333
+ case CLOCK_MONOTONIC :
334
+ tk_offset = TK_OFFS_MAX ;
335
+ break ;
336
+ case CLOCK_BOOTTIME :
337
+ tk_offset = TK_OFFS_BOOT ;
338
+ break ;
339
+ case CLOCK_TAI :
340
+ tk_offset = TK_OFFS_TAI ;
341
+ break ;
342
+ default :
343
+ NL_SET_ERR_MSG (extack , "Invalid 'clockid'" );
344
+ return - EINVAL ;
345
+ }
346
+ }
347
+
311
348
parm = nla_data (tb [TCA_GATE_PARMS ]);
312
349
index = parm -> index ;
313
350
@@ -331,10 +368,6 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
331
368
tcf_idr_release (* a , bind );
332
369
return - EEXIST ;
333
370
}
334
- if (ret == ACT_P_CREATED ) {
335
- to_gate (* a )-> param .tcfg_clockid = -1 ;
336
- INIT_LIST_HEAD (& (to_gate (* a )-> param .entries ));
337
- }
338
371
339
372
if (tb [TCA_GATE_PRIORITY ])
340
373
prio = nla_get_s32 (tb [TCA_GATE_PRIORITY ]);
@@ -345,77 +378,49 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
345
378
if (tb [TCA_GATE_FLAGS ])
346
379
gflags = nla_get_u32 (tb [TCA_GATE_FLAGS ]);
347
380
348
- if (tb [TCA_GATE_CLOCKID ]) {
349
- clockid = nla_get_s32 (tb [TCA_GATE_CLOCKID ]);
350
- switch (clockid ) {
351
- case CLOCK_REALTIME :
352
- tk_offset = TK_OFFS_REAL ;
353
- break ;
354
- case CLOCK_MONOTONIC :
355
- tk_offset = TK_OFFS_MAX ;
356
- break ;
357
- case CLOCK_BOOTTIME :
358
- tk_offset = TK_OFFS_BOOT ;
359
- break ;
360
- case CLOCK_TAI :
361
- tk_offset = TK_OFFS_TAI ;
362
- break ;
363
- default :
364
- NL_SET_ERR_MSG (extack , "Invalid 'clockid'" );
365
- goto release_idr ;
366
- }
367
- }
381
+ gact = to_gate (* a );
382
+ if (ret == ACT_P_CREATED )
383
+ INIT_LIST_HEAD (& gact -> param .entries );
368
384
369
385
err = tcf_action_check_ctrlact (parm -> action , tp , & goto_ch , extack );
370
386
if (err < 0 )
371
387
goto release_idr ;
372
388
373
- gact = to_gate (* a );
374
-
375
389
spin_lock_bh (& gact -> tcf_lock );
376
390
p = & gact -> param ;
377
391
378
- if (tb [TCA_GATE_CYCLE_TIME ]) {
379
- p -> tcfg_cycletime = nla_get_u64 (tb [TCA_GATE_CYCLE_TIME ]);
380
- if (!p -> tcfg_cycletime_ext )
381
- goto chain_put ;
382
- }
392
+ if (tb [TCA_GATE_CYCLE_TIME ])
393
+ cycletime = nla_get_u64 (tb [TCA_GATE_CYCLE_TIME ]);
383
394
384
395
if (tb [TCA_GATE_ENTRY_LIST ]) {
385
396
err = parse_gate_list (tb [TCA_GATE_ENTRY_LIST ], p , extack );
386
397
if (err < 0 )
387
398
goto chain_put ;
388
399
}
389
400
390
- if (!p -> tcfg_cycletime ) {
401
+ if (!cycletime ) {
391
402
struct tcfg_gate_entry * entry ;
392
403
ktime_t cycle = 0 ;
393
404
394
405
list_for_each_entry (entry , & p -> entries , list )
395
406
cycle = ktime_add_ns (cycle , entry -> interval );
396
- p -> tcfg_cycletime = cycle ;
407
+ cycletime = cycle ;
408
+ if (!cycletime ) {
409
+ err = - EINVAL ;
410
+ goto chain_put ;
411
+ }
397
412
}
413
+ p -> tcfg_cycletime = cycletime ;
398
414
399
415
if (tb [TCA_GATE_CYCLE_TIME_EXT ])
400
416
p -> tcfg_cycletime_ext =
401
417
nla_get_u64 (tb [TCA_GATE_CYCLE_TIME_EXT ]);
402
418
419
+ gate_setup_timer (gact , basetime , tk_offset , clockid ,
420
+ ret == ACT_P_CREATED );
403
421
p -> tcfg_priority = prio ;
404
- p -> tcfg_basetime = basetime ;
405
- p -> tcfg_clockid = clockid ;
406
422
p -> tcfg_flags = gflags ;
407
-
408
- gact -> tk_offset = tk_offset ;
409
- hrtimer_init (& gact -> hitimer , clockid , HRTIMER_MODE_ABS_SOFT );
410
- gact -> hitimer .function = gate_timer_func ;
411
-
412
- err = gate_get_start_time (gact , & start );
413
- if (err < 0 ) {
414
- NL_SET_ERR_MSG (extack ,
415
- "Internal error: failed get start time" );
416
- release_entry_list (& p -> entries );
417
- goto chain_put ;
418
- }
423
+ gate_get_start_time (gact , & start );
419
424
420
425
gact -> current_close_time = start ;
421
426
gact -> current_gate_status = GATE_ACT_GATE_OPEN | GATE_ACT_PENDING ;
@@ -443,6 +448,13 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
443
448
if (goto_ch )
444
449
tcf_chain_put_by_act (goto_ch );
445
450
release_idr :
451
+ /* action is not inserted in any list: it's safe to init hitimer
452
+ * without taking tcf_lock.
453
+ */
454
+ if (ret == ACT_P_CREATED )
455
+ gate_setup_timer (gact , gact -> param .tcfg_basetime ,
456
+ gact -> tk_offset , gact -> param .tcfg_clockid ,
457
+ true);
446
458
tcf_idr_release (* a , bind );
447
459
return err ;
448
460
}
@@ -453,9 +465,7 @@ static void tcf_gate_cleanup(struct tc_action *a)
453
465
struct tcf_gate_params * p ;
454
466
455
467
p = & gact -> param ;
456
- if (p -> tcfg_clockid != -1 )
457
- hrtimer_cancel (& gact -> hitimer );
458
-
468
+ hrtimer_cancel (& gact -> hitimer );
459
469
release_entry_list (& p -> entries );
460
470
}
461
471
0 commit comments