net_sched: sch_hfsc: implement lockless accesses to q->defcls
authorEric Dumazet <edumazet@google.com>
Thu, 18 Apr 2024 07:32:45 +0000 (07:32 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 19 Apr 2024 10:34:08 +0000 (11:34 +0100)
Instead of relying on RTNL, hfsc_dump_qdisc() can use READ_ONCE()
annotation, paired with WRITE_ONCE() one in hfsc_change_qdisc().

Use READ_ONCE(q->defcls) in hfsc_classify() to
no longer acquire qdisc lock from hfsc_change_qdisc().

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sched/sch_hfsc.c

index 4e626df742d7a937c219ae9755816f099b6f0680..c287bf8423b47b7ca022fc2e6ca19b77f3ec13a0 100644 (file)
@@ -1174,7 +1174,8 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
        }
 
        /* classification failed, try default class */
-       cl = hfsc_find_class(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch);
+       cl = hfsc_find_class(TC_H_MAKE(TC_H_MAJ(sch->handle),
+                                      READ_ONCE(q->defcls)), sch);
        if (cl == NULL || cl->level > 0)
                return NULL;
 
@@ -1443,9 +1444,7 @@ hfsc_change_qdisc(struct Qdisc *sch, struct nlattr *opt,
                return -EINVAL;
        qopt = nla_data(opt);
 
-       sch_tree_lock(sch);
-       q->defcls = qopt->defcls;
-       sch_tree_unlock(sch);
+       WRITE_ONCE(q->defcls, qopt->defcls);
 
        return 0;
 }
@@ -1525,7 +1524,7 @@ hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
        unsigned char *b = skb_tail_pointer(skb);
        struct tc_hfsc_qopt qopt;
 
-       qopt.defcls = q->defcls;
+       qopt.defcls = READ_ONCE(q->defcls);
        if (nla_put(skb, TCA_OPTIONS, sizeof(qopt), &qopt))
                goto nla_put_failure;
        return skb->len;