hc
2024-09-20 cf4ce59b3b70238352c7f1729f0f7223214828ad
kernel/net/sctp/stream.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* SCTP kernel implementation
23 * (C) Copyright IBM Corp. 2001, 2004
34 * Copyright (c) 1999-2000 Cisco, Inc.
....@@ -7,22 +8,6 @@
78 * This file is part of the SCTP kernel implementation
89 *
910 * This file contains sctp stream maniuplation primitives and helpers.
10
- *
11
- * This SCTP implementation is free software;
12
- * you can redistribute it and/or modify it under the terms of
13
- * the GNU General Public License as published by
14
- * the Free Software Foundation; either version 2, or (at your option)
15
- * any later version.
16
- *
17
- * This SCTP implementation is distributed in the hope that it
18
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
19
- * ************************
20
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21
- * See the GNU General Public License for more details.
22
- *
23
- * You should have received a copy of the GNU General Public License
24
- * along with GNU CC; see the file COPYING. If not, see
25
- * <http://www.gnu.org/licenses/>.
2611 *
2712 * Please send any bug reports or fixes you make to the
2813 * email address(es):
....@@ -36,66 +21,6 @@
3621 #include <net/sctp/sctp.h>
3722 #include <net/sctp/sm.h>
3823 #include <net/sctp/stream_sched.h>
39
-
40
-static struct flex_array *fa_alloc(size_t elem_size, size_t elem_count,
41
- gfp_t gfp)
42
-{
43
- struct flex_array *result;
44
- int err;
45
-
46
- result = flex_array_alloc(elem_size, elem_count, gfp);
47
- if (result) {
48
- err = flex_array_prealloc(result, 0, elem_count, gfp);
49
- if (err) {
50
- flex_array_free(result);
51
- result = NULL;
52
- }
53
- }
54
-
55
- return result;
56
-}
57
-
58
-static void fa_free(struct flex_array *fa)
59
-{
60
- if (fa)
61
- flex_array_free(fa);
62
-}
63
-
64
-static void fa_copy(struct flex_array *fa, struct flex_array *from,
65
- size_t index, size_t count)
66
-{
67
- void *elem;
68
-
69
- while (count--) {
70
- elem = flex_array_get(from, index);
71
- flex_array_put(fa, index, elem, 0);
72
- index++;
73
- }
74
-}
75
-
76
-static void fa_zero(struct flex_array *fa, size_t index, size_t count)
77
-{
78
- void *elem;
79
-
80
- while (count--) {
81
- elem = flex_array_get(fa, index);
82
- memset(elem, 0, fa->element_size);
83
- index++;
84
- }
85
-}
86
-
87
-static size_t fa_index(struct flex_array *fa, void *elem, size_t count)
88
-{
89
- size_t index = 0;
90
-
91
- while (count--) {
92
- if (elem == flex_array_get(fa, index))
93
- break;
94
- index++;
95
- }
96
-
97
- return index;
98
-}
9924
10025 static void sctp_stream_shrink_out(struct sctp_stream *stream, __u16 outcnt)
10126 {
....@@ -127,6 +52,19 @@
12752 }
12853 }
12954
55
+static void sctp_stream_free_ext(struct sctp_stream *stream, __u16 sid)
56
+{
57
+ struct sctp_sched_ops *sched;
58
+
59
+ if (!SCTP_SO(stream, sid)->ext)
60
+ return;
61
+
62
+ sched = sctp_sched_ops_from_stream(stream);
63
+ sched->free_sid(stream, sid);
64
+ kfree(SCTP_SO(stream, sid)->ext);
65
+ SCTP_SO(stream, sid)->ext = NULL;
66
+}
67
+
13068 /* Migrates chunks from stream queues to new stream queues if needed,
13169 * but not across associations. Also, removes those chunks to streams
13270 * higher than the new max.
....@@ -145,68 +83,47 @@
14583 * sctp_stream_update will swap ->out pointers.
14684 */
14785 for (i = 0; i < outcnt; i++) {
148
- kfree(SCTP_SO(new, i)->ext);
86
+ sctp_stream_free_ext(new, i);
14987 SCTP_SO(new, i)->ext = SCTP_SO(stream, i)->ext;
15088 SCTP_SO(stream, i)->ext = NULL;
15189 }
15290 }
15391
154
- for (i = outcnt; i < stream->outcnt; i++) {
155
- kfree(SCTP_SO(stream, i)->ext);
156
- SCTP_SO(stream, i)->ext = NULL;
157
- }
92
+ for (i = outcnt; i < stream->outcnt; i++)
93
+ sctp_stream_free_ext(stream, i);
15894 }
15995
16096 static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
16197 gfp_t gfp)
16298 {
163
- struct flex_array *out;
164
- size_t elem_size = sizeof(struct sctp_stream_out);
99
+ int ret;
165100
166
- out = fa_alloc(elem_size, outcnt, gfp);
167
- if (!out)
168
- return -ENOMEM;
101
+ if (outcnt <= stream->outcnt)
102
+ goto out;
169103
170
- if (stream->out) {
171
- fa_copy(out, stream->out, 0, min(outcnt, stream->outcnt));
172
- if (stream->out_curr) {
173
- size_t index = fa_index(stream->out, stream->out_curr,
174
- stream->outcnt);
104
+ ret = genradix_prealloc(&stream->out, outcnt, gfp);
105
+ if (ret)
106
+ return ret;
175107
176
- BUG_ON(index == stream->outcnt);
177
- stream->out_curr = flex_array_get(out, index);
178
- }
179
- fa_free(stream->out);
180
- }
181
-
182
- if (outcnt > stream->outcnt)
183
- fa_zero(out, stream->outcnt, (outcnt - stream->outcnt));
184
-
185
- stream->out = out;
186
-
108
+out:
109
+ stream->outcnt = outcnt;
187110 return 0;
188111 }
189112
190113 static int sctp_stream_alloc_in(struct sctp_stream *stream, __u16 incnt,
191114 gfp_t gfp)
192115 {
193
- struct flex_array *in;
194
- size_t elem_size = sizeof(struct sctp_stream_in);
116
+ int ret;
195117
196
- in = fa_alloc(elem_size, incnt, gfp);
197
- if (!in)
198
- return -ENOMEM;
118
+ if (incnt <= stream->incnt)
119
+ goto out;
199120
200
- if (stream->in) {
201
- fa_copy(in, stream->in, 0, min(incnt, stream->incnt));
202
- fa_free(stream->in);
203
- }
121
+ ret = genradix_prealloc(&stream->in, incnt, gfp);
122
+ if (ret)
123
+ return ret;
204124
205
- if (incnt > stream->incnt)
206
- fa_zero(in, stream->incnt, (incnt - stream->incnt));
207
-
208
- stream->in = in;
209
-
125
+out:
126
+ stream->incnt = incnt;
210127 return 0;
211128 }
212129
....@@ -222,7 +139,7 @@
222139 * a new one with new outcnt to save memory if needed.
223140 */
224141 if (outcnt == stream->outcnt)
225
- goto in;
142
+ goto handle_in;
226143
227144 /* Filter out chunks queued on streams that won't exist anymore */
228145 sched->unsched_all(stream);
....@@ -231,30 +148,17 @@
231148
232149 ret = sctp_stream_alloc_out(stream, outcnt, gfp);
233150 if (ret)
234
- goto out;
151
+ return ret;
235152
236
- stream->outcnt = outcnt;
237153 for (i = 0; i < stream->outcnt; i++)
238154 SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
239155
240
-in:
156
+handle_in:
241157 sctp_stream_interleave_init(stream);
242158 if (!incnt)
243
- goto out;
159
+ return 0;
244160
245
- ret = sctp_stream_alloc_in(stream, incnt, gfp);
246
- if (ret) {
247
- sched->free(stream);
248
- fa_free(stream->out);
249
- stream->out = NULL;
250
- stream->outcnt = 0;
251
- goto out;
252
- }
253
-
254
- stream->incnt = incnt;
255
-
256
-out:
257
- return ret;
161
+ return sctp_stream_alloc_in(stream, incnt, gfp);
258162 }
259163
260164 int sctp_stream_init_ext(struct sctp_stream *stream, __u16 sid)
....@@ -281,11 +185,11 @@
281185 struct sctp_sched_ops *sched = sctp_sched_ops_from_stream(stream);
282186 int i;
283187
284
- sched->free(stream);
188
+ sched->unsched_all(stream);
285189 for (i = 0; i < stream->outcnt; i++)
286
- kfree(SCTP_SO(stream, i)->ext);
287
- fa_free(stream->out);
288
- fa_free(stream->in);
190
+ sctp_stream_free_ext(stream, i);
191
+ genradix_free(&stream->out);
192
+ genradix_free(&stream->in);
289193 }
290194
291195 void sctp_stream_clear(struct sctp_stream *stream)
....@@ -316,8 +220,8 @@
316220
317221 sched->sched_all(stream);
318222
319
- new->out = NULL;
320
- new->in = NULL;
223
+ new->out.tree.root = NULL;
224
+ new->in.tree.root = NULL;
321225 new->outcnt = 0;
322226 new->incnt = 0;
323227 }
....@@ -325,10 +229,9 @@
325229 static int sctp_send_reconf(struct sctp_association *asoc,
326230 struct sctp_chunk *chunk)
327231 {
328
- struct net *net = sock_net(asoc->base.sk);
329232 int retval = 0;
330233
331
- retval = sctp_primitive_RECONF(net, asoc, chunk);
234
+ retval = sctp_primitive_RECONF(asoc->base.net, asoc, chunk);
332235 if (retval)
333236 sctp_chunk_free(chunk);
334237
....@@ -569,8 +472,6 @@
569472 asoc->strreset_chunk = NULL;
570473 goto out;
571474 }
572
-
573
- stream->outcnt = outcnt;
574475
575476 asoc->strreset_outstanding = !!out + !!in;
576477