static void sctp_sched_prio_unsched_all(struct sctp_stream *stream);
+static struct sctp_stream_priorities *sctp_sched_prio_head_get(struct sctp_stream_priorities *p)
+{
+ p->users++;
+ return p;
+}
+
+static void sctp_sched_prio_head_put(struct sctp_stream_priorities *p)
+{
+ if (p && --p->users == 0)
+ kfree(p);
+}
+
static struct sctp_stream_priorities *sctp_sched_prio_new_head(
struct sctp_stream *stream, int prio, gfp_t gfp)
{
INIT_LIST_HEAD(&p->active);
p->next = NULL;
p->prio = prio;
+ p->users = 1;
return p;
}
*/
list_for_each_entry(p, &stream->prio_list, prio_sched) {
if (p->prio == prio)
- return p;
+ return sctp_sched_prio_head_get(p);
if (p->prio > prio)
break;
}
*/
break;
if (p->prio == prio)
- return p;
+ return sctp_sched_prio_head_get(p);
}
/* If not even there, allocate a new one. */
struct sctp_stream_out_ext *soute = sout->ext;
struct sctp_stream_priorities *prio_head, *old;
bool reschedule = false;
- int i;
+
+ old = soute->prio_head;
+ if (old && old->prio == prio)
+ return 0;
prio_head = sctp_sched_prio_get_head(stream, prio, gfp);
if (!prio_head)
return -ENOMEM;
reschedule = sctp_sched_prio_unsched(soute);
- old = soute->prio_head;
soute->prio_head = prio_head;
if (reschedule)
sctp_sched_prio_sched(stream, soute);
- if (!old)
- /* Happens when we set the priority for the first time */
- return 0;
-
- for (i = 0; i < stream->outcnt; i++) {
- soute = SCTP_SO(stream, i)->ext;
- if (soute && soute->prio_head == old)
- /* It's still in use, nothing else to do here. */
- return 0;
- }
-
- /* No hits, we are good to free it. */
- kfree(old);
-
+ sctp_sched_prio_head_put(old);
return 0;
}
static void sctp_sched_prio_free_sid(struct sctp_stream *stream, __u16 sid)
{
- struct sctp_stream_priorities *prio = SCTP_SO(stream, sid)->ext->prio_head;
- int i;
-
- if (!prio)
- return;
-
+ sctp_sched_prio_head_put(SCTP_SO(stream, sid)->ext->prio_head);
SCTP_SO(stream, sid)->ext->prio_head = NULL;
- for (i = 0; i < stream->outcnt; i++) {
- if (SCTP_SO(stream, i)->ext &&
- SCTP_SO(stream, i)->ext->prio_head == prio)
- return;
- }
-
- kfree(prio);
}
static void sctp_sched_prio_free(struct sctp_stream *stream)