| .. | .. |
|---|
| 773 | 773 | * signed 16 bit values. |
|---|
| 774 | 774 | */ |
|---|
| 775 | 775 | |
|---|
| 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) |
|---|
| 778 | 777 | { |
|---|
| 779 | 778 | size_t n = nla_len(attr)/sizeof(__s16); |
|---|
| 780 | 779 | const __s16 *data = nla_data(attr); |
|---|
| 781 | | - spinlock_t *root_lock; |
|---|
| 782 | 780 | struct disttable *d; |
|---|
| 783 | 781 | int i; |
|---|
| 784 | 782 | |
|---|
| .. | .. |
|---|
| 793 | 791 | for (i = 0; i < n; i++) |
|---|
| 794 | 792 | d->table[i] = data[i]; |
|---|
| 795 | 793 | |
|---|
| 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; |
|---|
| 803 | 795 | return 0; |
|---|
| 804 | 796 | } |
|---|
| 805 | 797 | |
|---|
| .. | .. |
|---|
| 956 | 948 | { |
|---|
| 957 | 949 | struct netem_sched_data *q = qdisc_priv(sch); |
|---|
| 958 | 950 | struct nlattr *tb[TCA_NETEM_MAX + 1]; |
|---|
| 951 | + struct disttable *delay_dist = NULL; |
|---|
| 952 | + struct disttable *slot_dist = NULL; |
|---|
| 959 | 953 | struct tc_netem_qopt *qopt; |
|---|
| 960 | 954 | struct clgstate old_clg; |
|---|
| 961 | 955 | int old_loss_model = CLG_RANDOM; |
|---|
| .. | .. |
|---|
| 969 | 963 | if (ret < 0) |
|---|
| 970 | 964 | return ret; |
|---|
| 971 | 965 | |
|---|
| 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); |
|---|
| 972 | 979 | /* backup q->clg and q->loss_model */ |
|---|
| 973 | 980 | old_clg = q->clg; |
|---|
| 974 | 981 | old_loss_model = q->loss_model; |
|---|
| .. | .. |
|---|
| 977 | 984 | ret = get_loss_clg(q, tb[TCA_NETEM_LOSS]); |
|---|
| 978 | 985 | if (ret) { |
|---|
| 979 | 986 | q->loss_model = old_loss_model; |
|---|
| 980 | | - return ret; |
|---|
| 987 | + q->clg = old_clg; |
|---|
| 988 | + goto unlock; |
|---|
| 981 | 989 | } |
|---|
| 982 | 990 | } else { |
|---|
| 983 | 991 | q->loss_model = CLG_RANDOM; |
|---|
| 984 | 992 | } |
|---|
| 985 | 993 | |
|---|
| 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); |
|---|
| 1000 | 998 | sch->limit = qopt->limit; |
|---|
| 1001 | 999 | |
|---|
| 1002 | 1000 | q->latency = PSCHED_TICKS2NS(qopt->latency); |
|---|
| .. | .. |
|---|
| 1044 | 1042 | /* capping jitter to the range acceptable by tabledist() */ |
|---|
| 1045 | 1043 | q->jitter = min_t(s64, abs(q->jitter), INT_MAX); |
|---|
| 1046 | 1044 | |
|---|
| 1047 | | - return ret; |
|---|
| 1045 | +unlock: |
|---|
| 1046 | + sch_tree_unlock(sch); |
|---|
| 1048 | 1047 | |
|---|
| 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); |
|---|
| 1056 | 1051 | return ret; |
|---|
| 1057 | 1052 | } |
|---|
| 1058 | 1053 | |
|---|