hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/sched/sch_netem.c
....@@ -773,12 +773,10 @@
773773 * signed 16 bit values.
774774 */
775775
776
-static int get_dist_table(struct Qdisc *sch, struct disttable **tbl,
777
- const struct nlattr *attr)
776
+static int get_dist_table(struct disttable **tbl, const struct nlattr *attr)
778777 {
779778 size_t n = nla_len(attr)/sizeof(__s16);
780779 const __s16 *data = nla_data(attr);
781
- spinlock_t *root_lock;
782780 struct disttable *d;
783781 int i;
784782
....@@ -793,13 +791,7 @@
793791 for (i = 0; i < n; i++)
794792 d->table[i] = data[i];
795793
796
- root_lock = qdisc_root_sleeping_lock(sch);
797
-
798
- spin_lock_bh(root_lock);
799
- swap(*tbl, d);
800
- spin_unlock_bh(root_lock);
801
-
802
- dist_free(d);
794
+ *tbl = d;
803795 return 0;
804796 }
805797
....@@ -956,6 +948,8 @@
956948 {
957949 struct netem_sched_data *q = qdisc_priv(sch);
958950 struct nlattr *tb[TCA_NETEM_MAX + 1];
951
+ struct disttable *delay_dist = NULL;
952
+ struct disttable *slot_dist = NULL;
959953 struct tc_netem_qopt *qopt;
960954 struct clgstate old_clg;
961955 int old_loss_model = CLG_RANDOM;
....@@ -969,6 +963,19 @@
969963 if (ret < 0)
970964 return ret;
971965
966
+ if (tb[TCA_NETEM_DELAY_DIST]) {
967
+ ret = get_dist_table(&delay_dist, tb[TCA_NETEM_DELAY_DIST]);
968
+ if (ret)
969
+ goto table_free;
970
+ }
971
+
972
+ if (tb[TCA_NETEM_SLOT_DIST]) {
973
+ ret = get_dist_table(&slot_dist, tb[TCA_NETEM_SLOT_DIST]);
974
+ if (ret)
975
+ goto table_free;
976
+ }
977
+
978
+ sch_tree_lock(sch);
972979 /* backup q->clg and q->loss_model */
973980 old_clg = q->clg;
974981 old_loss_model = q->loss_model;
....@@ -977,26 +984,17 @@
977984 ret = get_loss_clg(q, tb[TCA_NETEM_LOSS]);
978985 if (ret) {
979986 q->loss_model = old_loss_model;
980
- return ret;
987
+ q->clg = old_clg;
988
+ goto unlock;
981989 }
982990 } else {
983991 q->loss_model = CLG_RANDOM;
984992 }
985993
986
- if (tb[TCA_NETEM_DELAY_DIST]) {
987
- ret = get_dist_table(sch, &q->delay_dist,
988
- tb[TCA_NETEM_DELAY_DIST]);
989
- if (ret)
990
- goto get_table_failure;
991
- }
992
-
993
- if (tb[TCA_NETEM_SLOT_DIST]) {
994
- ret = get_dist_table(sch, &q->slot_dist,
995
- tb[TCA_NETEM_SLOT_DIST]);
996
- if (ret)
997
- goto get_table_failure;
998
- }
999
-
994
+ if (delay_dist)
995
+ swap(q->delay_dist, delay_dist);
996
+ if (slot_dist)
997
+ swap(q->slot_dist, slot_dist);
1000998 sch->limit = qopt->limit;
1001999
10021000 q->latency = PSCHED_TICKS2NS(qopt->latency);
....@@ -1044,15 +1042,12 @@
10441042 /* capping jitter to the range acceptable by tabledist() */
10451043 q->jitter = min_t(s64, abs(q->jitter), INT_MAX);
10461044
1047
- return ret;
1045
+unlock:
1046
+ sch_tree_unlock(sch);
10481047
1049
-get_table_failure:
1050
- /* recover clg and loss_model, in case of
1051
- * q->clg and q->loss_model were modified
1052
- * in get_loss_clg()
1053
- */
1054
- q->clg = old_clg;
1055
- q->loss_model = old_loss_model;
1048
+table_free:
1049
+ dist_free(delay_dist);
1050
+ dist_free(slot_dist);
10561051 return ret;
10571052 }
10581053