Skip to content

Commit a9d6227

Browse files
vcgomesdavem330
authored andcommitted
taprio: Fix still allowing changing the flags during runtime
Because 'q->flags' starts as zero, and zero is a valid value, we aren't able to detect the transition from zero to something else during "runtime". The solution is to initialize 'q->flags' with an invalid value, so we can detect if 'q->flags' was set by the user or not. To better solidify the behavior, 'flags' handling is moved to a separate function. The behavior is: - 'flags' if unspecified by the user, is assumed to be zero; - 'flags' cannot change during "runtime" (i.e. a change() request cannot modify it); With this new function we can remove taprio_flags, which should reduce the risk of future accidents. Allowing flags to be changed was causing the following RCU stall: [ 1730.558249] rcu: INFO: rcu_preempt detected stalls on CPUs/tasks: [ 1730.558258] rcu: 6-...0: (190 ticks this GP) idle=922/0/0x1 softirq=25580/25582 fqs=16250 [ 1730.558264] (detected by 2, t=65002 jiffies, g=33017, q=81) [ 1730.558269] Sending NMI from CPU 2 to CPUs 6: [ 1730.559277] NMI backtrace for cpu 6 [ 1730.559277] CPU: 6 PID: 0 Comm: swapper/6 Tainted: G E 5.5.0-rc6+ #35 [ 1730.559278] Hardware name: Gigabyte Technology Co., Ltd. Z390 AORUS ULTRA/Z390 AORUS ULTRA-CF, BIOS F7 03/14/2019 [ 1730.559278] RIP: 0010:__hrtimer_run_queues+0xe2/0x440 [ 1730.559278] Code: 48 8b 43 28 4c 89 ff 48 8b 75 c0 48 89 45 c8 e8 f4 bb 7c 00 0f 1f 44 00 00 65 8b 05 40 31 f0 68 89 c0 48 0f a3 05 3e 5c 25 01 <0f> 82 fc 01 00 00 48 8b 45 c8 48 89 df ff d0 89 45 c8 0f 1f 44 00 [ 1730.559279] RSP: 0018:ffff9970802d8f10 EFLAGS: 00000083 [ 1730.559279] RAX: 0000000000000006 RBX: ffff8b31645bff38 RCX: 0000000000000000 [ 1730.559280] RDX: 0000000000000000 RSI: ffffffff9710f2ec RDI: ffffffff978daf0e [ 1730.559280] RBP: ffff9970802d8f68 R08: 0000000000000000 R09: 0000000000000000 [ 1730.559280] R10: 0000018336d7944e R11: 0000000000000001 R12: ffff8b316e39f9c0 [ 1730.559281] R13: ffff8b316e39f940 R14: ffff8b316e39f998 R15: ffff8b316e39f7c0 [ 1730.559281] FS: 0000000000000000(0000) GS:ffff8b316e380000(0000) knlGS:0000000000000000 [ 1730.559281] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1730.559281] CR2: 00007f1105303760 CR3: 0000000227210005 CR4: 00000000003606e0 [ 1730.559282] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 1730.559282] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 1730.559282] Call Trace: [ 1730.559282] <IRQ> [ 1730.559283] ? taprio_dequeue_soft+0x2d0/0x2d0 [sch_taprio] [ 1730.559283] hrtimer_interrupt+0x104/0x220 [ 1730.559283] ? irqtime_account_irq+0x34/0xa0 [ 1730.559283] smp_apic_timer_interrupt+0x6d/0x230 [ 1730.559284] apic_timer_interrupt+0xf/0x20 [ 1730.559284] </IRQ> [ 1730.559284] RIP: 0010:cpu_idle_poll+0x35/0x1a0 [ 1730.559285] Code: 88 82 ff 65 44 8b 25 12 7d 73 68 0f 1f 44 00 00 e8 90 c3 89 ff fb 65 48 8b 1c 25 c0 7e 01 00 48 8b 03 a8 08 74 0b eb 1c f3 90 <48> 8b 03 a8 08 75 13 8b 05 be a8 a8 00 85 c0 75 ed e8 75 48 84 ff [ 1730.559285] RSP: 0018:ffff997080137ea8 EFLAGS: 00000202 ORIG_RAX: ffffffffffffff13 [ 1730.559285] RAX: 0000000000000001 RBX: ffff8b316bc3c580 RCX: 0000000000000000 [ 1730.559286] RDX: 0000000000000001 RSI: 000000002819aad9 RDI: ffffffff978da730 [ 1730.559286] RBP: ffff997080137ec0 R08: 0000018324a6d387 R09: 0000000000000000 [ 1730.559286] R10: 0000000000000400 R11: 0000000000000001 R12: 0000000000000006 [ 1730.559286] R13: ffff8b316bc3c580 R14: 0000000000000000 R15: 0000000000000000 [ 1730.559287] ? cpu_idle_poll+0x20/0x1a0 [ 1730.559287] ? cpu_idle_poll+0x20/0x1a0 [ 1730.559287] do_idle+0x4d/0x1f0 [ 1730.559287] ? complete+0x44/0x50 [ 1730.559288] cpu_startup_entry+0x1b/0x20 [ 1730.559288] start_secondary+0x142/0x180 [ 1730.559288] secondary_startup_64+0xb6/0xc0 [ 1776.686313] nvme nvme0: I/O 96 QID 1 timeout, completion polled Fixes: 4cfd577 ("taprio: Add support for txtime-assist mode") Signed-off-by: Vinicius Costa Gomes <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5652e63 commit a9d6227

File tree

1 file changed

+41
-20
lines changed

1 file changed

+41
-20
lines changed

net/sched/sch_taprio.c

+41-20
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ static DEFINE_SPINLOCK(taprio_list_lock);
3131

3232
#define TXTIME_ASSIST_IS_ENABLED(flags) ((flags) & TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST)
3333
#define FULL_OFFLOAD_IS_ENABLED(flags) ((flags) & TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD)
34+
#define TAPRIO_FLAGS_INVALID U32_MAX
3435

3536
struct sched_entry {
3637
struct list_head list;
@@ -1367,6 +1368,33 @@ static int taprio_mqprio_cmp(const struct net_device *dev,
13671368
return 0;
13681369
}
13691370

1371+
/* The semantics of the 'flags' argument in relation to 'change()'
1372+
* requests, are interpreted following two rules (which are applied in
1373+
* this order): (1) an omitted 'flags' argument is interpreted as
1374+
* zero; (2) the 'flags' of a "running" taprio instance cannot be
1375+
* changed.
1376+
*/
1377+
static int taprio_new_flags(const struct nlattr *attr, u32 old,
1378+
struct netlink_ext_ack *extack)
1379+
{
1380+
u32 new = 0;
1381+
1382+
if (attr)
1383+
new = nla_get_u32(attr);
1384+
1385+
if (old != TAPRIO_FLAGS_INVALID && old != new) {
1386+
NL_SET_ERR_MSG_MOD(extack, "Changing 'flags' of a running schedule is not supported");
1387+
return -EOPNOTSUPP;
1388+
}
1389+
1390+
if (!taprio_flags_valid(new)) {
1391+
NL_SET_ERR_MSG_MOD(extack, "Specified 'flags' are not valid");
1392+
return -EINVAL;
1393+
}
1394+
1395+
return new;
1396+
}
1397+
13701398
static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
13711399
struct netlink_ext_ack *extack)
13721400
{
@@ -1375,7 +1403,6 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
13751403
struct taprio_sched *q = qdisc_priv(sch);
13761404
struct net_device *dev = qdisc_dev(sch);
13771405
struct tc_mqprio_qopt *mqprio = NULL;
1378-
u32 taprio_flags = 0;
13791406
unsigned long flags;
13801407
ktime_t start;
13811408
int i, err;
@@ -1388,21 +1415,14 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
13881415
if (tb[TCA_TAPRIO_ATTR_PRIOMAP])
13891416
mqprio = nla_data(tb[TCA_TAPRIO_ATTR_PRIOMAP]);
13901417

1391-
if (tb[TCA_TAPRIO_ATTR_FLAGS]) {
1392-
taprio_flags = nla_get_u32(tb[TCA_TAPRIO_ATTR_FLAGS]);
1393-
1394-
if (q->flags != 0 && q->flags != taprio_flags) {
1395-
NL_SET_ERR_MSG_MOD(extack, "Changing 'flags' of a running schedule is not supported");
1396-
return -EOPNOTSUPP;
1397-
} else if (!taprio_flags_valid(taprio_flags)) {
1398-
NL_SET_ERR_MSG_MOD(extack, "Specified 'flags' are not valid");
1399-
return -EINVAL;
1400-
}
1418+
err = taprio_new_flags(tb[TCA_TAPRIO_ATTR_FLAGS],
1419+
q->flags, extack);
1420+
if (err < 0)
1421+
return err;
14011422

1402-
q->flags = taprio_flags;
1403-
}
1423+
q->flags = err;
14041424

1405-
err = taprio_parse_mqprio_opt(dev, mqprio, extack, taprio_flags);
1425+
err = taprio_parse_mqprio_opt(dev, mqprio, extack, q->flags);
14061426
if (err < 0)
14071427
return err;
14081428

@@ -1457,7 +1477,7 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
14571477
mqprio->prio_tc_map[i]);
14581478
}
14591479

1460-
if (FULL_OFFLOAD_IS_ENABLED(taprio_flags))
1480+
if (FULL_OFFLOAD_IS_ENABLED(q->flags))
14611481
err = taprio_enable_offload(dev, mqprio, q, new_admin, extack);
14621482
else
14631483
err = taprio_disable_offload(dev, q, extack);
@@ -1477,14 +1497,14 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
14771497
q->txtime_delay = nla_get_u32(tb[TCA_TAPRIO_ATTR_TXTIME_DELAY]);
14781498
}
14791499

1480-
if (!TXTIME_ASSIST_IS_ENABLED(taprio_flags) &&
1481-
!FULL_OFFLOAD_IS_ENABLED(taprio_flags) &&
1500+
if (!TXTIME_ASSIST_IS_ENABLED(q->flags) &&
1501+
!FULL_OFFLOAD_IS_ENABLED(q->flags) &&
14821502
!hrtimer_active(&q->advance_timer)) {
14831503
hrtimer_init(&q->advance_timer, q->clockid, HRTIMER_MODE_ABS);
14841504
q->advance_timer.function = advance_sched;
14851505
}
14861506

1487-
if (FULL_OFFLOAD_IS_ENABLED(taprio_flags)) {
1507+
if (FULL_OFFLOAD_IS_ENABLED(q->flags)) {
14881508
q->dequeue = taprio_dequeue_offload;
14891509
q->peek = taprio_peek_offload;
14901510
} else {
@@ -1501,7 +1521,7 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
15011521
goto unlock;
15021522
}
15031523

1504-
if (TXTIME_ASSIST_IS_ENABLED(taprio_flags)) {
1524+
if (TXTIME_ASSIST_IS_ENABLED(q->flags)) {
15051525
setup_txtime(q, new_admin, start);
15061526

15071527
if (!oper) {
@@ -1528,7 +1548,7 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
15281548

15291549
spin_unlock_irqrestore(&q->current_entry_lock, flags);
15301550

1531-
if (FULL_OFFLOAD_IS_ENABLED(taprio_flags))
1551+
if (FULL_OFFLOAD_IS_ENABLED(q->flags))
15321552
taprio_offload_config_changed(q);
15331553
}
15341554

@@ -1597,6 +1617,7 @@ static int taprio_init(struct Qdisc *sch, struct nlattr *opt,
15971617
* and get the valid one on taprio_change().
15981618
*/
15991619
q->clockid = -1;
1620+
q->flags = TAPRIO_FLAGS_INVALID;
16001621

16011622
spin_lock(&taprio_list_lock);
16021623
list_add(&q->taprio_list, &taprio_list);

0 commit comments

Comments
 (0)