| .. | .. |
|---|
| 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) |
|---|