.. | .. |
---|
25 | 25 | |
---|
26 | 26 | static void sctp_sched_prio_unsched_all(struct sctp_stream *stream); |
---|
27 | 27 | |
---|
| 28 | +static struct sctp_stream_priorities *sctp_sched_prio_head_get(struct sctp_stream_priorities *p) |
---|
| 29 | +{ |
---|
| 30 | + p->users++; |
---|
| 31 | + return p; |
---|
| 32 | +} |
---|
| 33 | + |
---|
| 34 | +static void sctp_sched_prio_head_put(struct sctp_stream_priorities *p) |
---|
| 35 | +{ |
---|
| 36 | + if (p && --p->users == 0) |
---|
| 37 | + kfree(p); |
---|
| 38 | +} |
---|
| 39 | + |
---|
28 | 40 | static struct sctp_stream_priorities *sctp_sched_prio_new_head( |
---|
29 | 41 | struct sctp_stream *stream, int prio, gfp_t gfp) |
---|
30 | 42 | { |
---|
.. | .. |
---|
38 | 50 | INIT_LIST_HEAD(&p->active); |
---|
39 | 51 | p->next = NULL; |
---|
40 | 52 | p->prio = prio; |
---|
| 53 | + p->users = 1; |
---|
41 | 54 | |
---|
42 | 55 | return p; |
---|
43 | 56 | } |
---|
.. | .. |
---|
53 | 66 | */ |
---|
54 | 67 | list_for_each_entry(p, &stream->prio_list, prio_sched) { |
---|
55 | 68 | if (p->prio == prio) |
---|
56 | | - return p; |
---|
| 69 | + return sctp_sched_prio_head_get(p); |
---|
57 | 70 | if (p->prio > prio) |
---|
58 | 71 | break; |
---|
59 | 72 | } |
---|
.. | .. |
---|
70 | 83 | */ |
---|
71 | 84 | break; |
---|
72 | 85 | if (p->prio == prio) |
---|
73 | | - return p; |
---|
| 86 | + return sctp_sched_prio_head_get(p); |
---|
74 | 87 | } |
---|
75 | 88 | |
---|
76 | 89 | /* If not even there, allocate a new one. */ |
---|
.. | .. |
---|
154 | 167 | struct sctp_stream_out_ext *soute = sout->ext; |
---|
155 | 168 | struct sctp_stream_priorities *prio_head, *old; |
---|
156 | 169 | bool reschedule = false; |
---|
157 | | - int i; |
---|
| 170 | + |
---|
| 171 | + old = soute->prio_head; |
---|
| 172 | + if (old && old->prio == prio) |
---|
| 173 | + return 0; |
---|
158 | 174 | |
---|
159 | 175 | prio_head = sctp_sched_prio_get_head(stream, prio, gfp); |
---|
160 | 176 | if (!prio_head) |
---|
161 | 177 | return -ENOMEM; |
---|
162 | 178 | |
---|
163 | 179 | reschedule = sctp_sched_prio_unsched(soute); |
---|
164 | | - old = soute->prio_head; |
---|
165 | 180 | soute->prio_head = prio_head; |
---|
166 | 181 | if (reschedule) |
---|
167 | 182 | sctp_sched_prio_sched(stream, soute); |
---|
168 | 183 | |
---|
169 | | - if (!old) |
---|
170 | | - /* Happens when we set the priority for the first time */ |
---|
171 | | - return 0; |
---|
172 | | - |
---|
173 | | - for (i = 0; i < stream->outcnt; i++) { |
---|
174 | | - soute = SCTP_SO(stream, i)->ext; |
---|
175 | | - if (soute && soute->prio_head == old) |
---|
176 | | - /* It's still in use, nothing else to do here. */ |
---|
177 | | - return 0; |
---|
178 | | - } |
---|
179 | | - |
---|
180 | | - /* No hits, we are good to free it. */ |
---|
181 | | - kfree(old); |
---|
182 | | - |
---|
| 184 | + sctp_sched_prio_head_put(old); |
---|
183 | 185 | return 0; |
---|
184 | 186 | } |
---|
185 | 187 | |
---|
.. | .. |
---|
206 | 208 | |
---|
207 | 209 | static void sctp_sched_prio_free_sid(struct sctp_stream *stream, __u16 sid) |
---|
208 | 210 | { |
---|
209 | | - struct sctp_stream_priorities *prio = SCTP_SO(stream, sid)->ext->prio_head; |
---|
210 | | - int i; |
---|
211 | | - |
---|
212 | | - if (!prio) |
---|
213 | | - return; |
---|
214 | | - |
---|
| 211 | + sctp_sched_prio_head_put(SCTP_SO(stream, sid)->ext->prio_head); |
---|
215 | 212 | SCTP_SO(stream, sid)->ext->prio_head = NULL; |
---|
216 | | - for (i = 0; i < stream->outcnt; i++) { |
---|
217 | | - if (SCTP_SO(stream, i)->ext && |
---|
218 | | - SCTP_SO(stream, i)->ext->prio_head == prio) |
---|
219 | | - return; |
---|
220 | | - } |
---|
221 | | - |
---|
222 | | - kfree(prio); |
---|
223 | 213 | } |
---|
224 | 214 | |
---|
225 | 215 | static void sctp_sched_prio_free(struct sctp_stream *stream) |
---|