Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sctp: delete free member from struct sctp_sched_ops

After commit 9ed7bfc79542 ("sctp: fix memory leak in
sctp_stream_outq_migrate()"), sctp_sched_set_sched() is the only
place calling sched->free(), and it can actually be replaced by
sched->free_sid() on each stream, and yet there's already a loop
to traverse all streams in sctp_sched_set_sched().

This patch adds a function sctp_sched_free_sched() where it calls
sched->free_sid() for each stream to replace sched->free() calls
in sctp_sched_set_sched() and then deletes the unused free member
from struct sctp_sched_ops.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Link: https://lore.kernel.org/r/e10aac150aca2686cb0bd0570299ec716da5a5c0.1669849471.git.lucien.xin@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Xin Long and committed by
Jakub Kicinski
7d802c80 e6a34faf

+20 -53
-2
include/net/sctp/stream_sched.h
··· 28 28 int (*init_sid)(struct sctp_stream *stream, __u16 sid, gfp_t gfp); 29 29 /* free a stream */ 30 30 void (*free_sid)(struct sctp_stream *stream, __u16 sid); 31 - /* Frees the entire thing */ 32 - void (*free)(struct sctp_stream *stream); 33 31 34 32 /* Enqueue a chunk */ 35 33 void (*enqueue)(struct sctp_outq *q, struct sctp_datamsg *msg);
+20 -18
net/sctp/stream_sched.c
··· 50 50 { 51 51 } 52 52 53 - static void sctp_sched_fcfs_free(struct sctp_stream *stream) 54 - { 55 - } 56 - 57 53 static void sctp_sched_fcfs_enqueue(struct sctp_outq *q, 58 54 struct sctp_datamsg *msg) 59 55 { ··· 97 101 .init = sctp_sched_fcfs_init, 98 102 .init_sid = sctp_sched_fcfs_init_sid, 99 103 .free_sid = sctp_sched_fcfs_free_sid, 100 - .free = sctp_sched_fcfs_free, 101 104 .enqueue = sctp_sched_fcfs_enqueue, 102 105 .dequeue = sctp_sched_fcfs_dequeue, 103 106 .dequeue_done = sctp_sched_fcfs_dequeue_done, ··· 126 131 sctp_sched_ops_rr_init(); 127 132 } 128 133 134 + static void sctp_sched_free_sched(struct sctp_stream *stream) 135 + { 136 + struct sctp_sched_ops *sched = sctp_sched_ops_from_stream(stream); 137 + struct sctp_stream_out_ext *soute; 138 + int i; 139 + 140 + sched->unsched_all(stream); 141 + for (i = 0; i < stream->outcnt; i++) { 142 + soute = SCTP_SO(stream, i)->ext; 143 + if (!soute) 144 + continue; 145 + sched->free_sid(stream, i); 146 + /* Give the next scheduler a clean slate. */ 147 + memset_after(soute, 0, outq); 148 + } 149 + } 150 + 129 151 int sctp_sched_set_sched(struct sctp_association *asoc, 130 152 enum sctp_sched_type sched) 131 153 { ··· 158 146 if (sched > SCTP_SS_MAX) 159 147 return -EINVAL; 160 148 161 - if (old) { 162 - old->free(&asoc->stream); 163 - 164 - /* Give the next scheduler a clean slate. */ 165 - for (i = 0; i < asoc->stream.outcnt; i++) { 166 - struct sctp_stream_out_ext *ext = SCTP_SO(&asoc->stream, i)->ext; 167 - 168 - if (!ext) 169 - continue; 170 - memset_after(ext, 0, outq); 171 - } 172 - } 149 + if (old) 150 + sctp_sched_free_sched(&asoc->stream); 173 151 174 152 asoc->outqueue.sched = n; 175 153 n->init(&asoc->stream); ··· 183 181 return ret; 184 182 185 183 err: 186 - n->free(&asoc->stream); 184 + sctp_sched_free_sched(&asoc->stream); 187 185 asoc->outqueue.sched = &sctp_sched_fcfs; /* Always safe */ 188 186 189 187 return ret;
-27
net/sctp/stream_sched_prio.c
··· 222 222 kfree(prio); 223 223 } 224 224 225 - static void sctp_sched_prio_free(struct sctp_stream *stream) 226 - { 227 - struct sctp_stream_priorities *prio, *n; 228 - LIST_HEAD(list); 229 - int i; 230 - 231 - /* As we don't keep a list of priorities, to avoid multiple 232 - * frees we have to do it in 3 steps: 233 - * 1. unsched everyone, so the lists are free to use in 2. 234 - * 2. build the list of the priorities 235 - * 3. free the list 236 - */ 237 - sctp_sched_prio_unsched_all(stream); 238 - for (i = 0; i < stream->outcnt; i++) { 239 - if (!SCTP_SO(stream, i)->ext) 240 - continue; 241 - prio = SCTP_SO(stream, i)->ext->prio_head; 242 - if (prio && list_empty(&prio->prio_sched)) 243 - list_add(&prio->prio_sched, &list); 244 - } 245 - list_for_each_entry_safe(prio, n, &list, prio_sched) { 246 - list_del_init(&prio->prio_sched); 247 - kfree(prio); 248 - } 249 - } 250 - 251 225 static void sctp_sched_prio_enqueue(struct sctp_outq *q, 252 226 struct sctp_datamsg *msg) 253 227 { ··· 316 342 .init = sctp_sched_prio_init, 317 343 .init_sid = sctp_sched_prio_init_sid, 318 344 .free_sid = sctp_sched_prio_free_sid, 319 - .free = sctp_sched_prio_free, 320 345 .enqueue = sctp_sched_prio_enqueue, 321 346 .dequeue = sctp_sched_prio_dequeue, 322 347 .dequeue_done = sctp_sched_prio_dequeue_done,
-6
net/sctp/stream_sched_rr.c
··· 94 94 { 95 95 } 96 96 97 - static void sctp_sched_rr_free(struct sctp_stream *stream) 98 - { 99 - sctp_sched_rr_unsched_all(stream); 100 - } 101 - 102 97 static void sctp_sched_rr_enqueue(struct sctp_outq *q, 103 98 struct sctp_datamsg *msg) 104 99 { ··· 177 182 .init = sctp_sched_rr_init, 178 183 .init_sid = sctp_sched_rr_init_sid, 179 184 .free_sid = sctp_sched_rr_free_sid, 180 - .free = sctp_sched_rr_free, 181 185 .enqueue = sctp_sched_rr_enqueue, 182 186 .dequeue = sctp_sched_rr_dequeue, 183 187 .dequeue_done = sctp_sched_rr_dequeue_done,