Skip to content

Commit f952be7

Browse files
marceloleitnerdavem330
authored andcommitted
sctp: introduce struct sctp_stream_out_ext
With the stream schedulers, sctp_stream_out will become too big to be allocated by kmalloc and as we need to allocate with BH disabled, we cannot use __vmalloc in sctp_stream_init(). This patch moves out the stats from sctp_stream_out to sctp_stream_out_ext, which will be allocated only when the application tries to sendmsg something on it. Just the introduction of sctp_stream_out_ext would already fix the issue described above by splitting the allocation in two. Moving the stats to it also reduces the pressure on the allocator as we will ask for less memory atomically when creating the socket and we will use GFP_KERNEL later. Then, for stream schedulers, we will just use sctp_stream_out_ext. Tested-by: Xin Long <[email protected]> Signed-off-by: Marcelo Ricardo Leitner <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1fdb8d8 commit f952be7

File tree

5 files changed

+50
-13
lines changed

5 files changed

+50
-13
lines changed

include/net/sctp/structs.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ struct sctp_ulpq;
8484
struct sctp_ep_common;
8585
struct crypto_shash;
8686
struct sctp_stream;
87+
struct sctp_stream_out;
8788

8889

8990
#include <net/sctp/tsnmap.h>
@@ -380,6 +381,7 @@ struct sctp_sender_hb_info {
380381

381382
int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
382383
gfp_t gfp);
384+
int sctp_stream_init_ext(struct sctp_stream *stream, __u16 sid);
383385
void sctp_stream_free(struct sctp_stream *stream);
384386
void sctp_stream_clear(struct sctp_stream *stream);
385387
void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new);
@@ -1315,11 +1317,15 @@ struct sctp_inithdr_host {
13151317
__u32 initial_tsn;
13161318
};
13171319

1320+
struct sctp_stream_out_ext {
1321+
__u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1];
1322+
__u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1];
1323+
};
1324+
13181325
struct sctp_stream_out {
13191326
__u16 ssn;
13201327
__u8 state;
1321-
__u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1];
1322-
__u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1];
1328+
struct sctp_stream_out_ext *ext;
13231329
};
13241330

13251331
struct sctp_stream_in {

net/sctp/chunk.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,10 +311,10 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
311311

312312
if (chunk->sent_count) {
313313
chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
314-
streamout->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
314+
streamout->ext->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
315315
} else {
316316
chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
317-
streamout->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
317+
streamout->ext->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
318318
}
319319
return 1;
320320
} else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) &&
@@ -323,7 +323,7 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
323323
&chunk->asoc->stream.out[chunk->sinfo.sinfo_stream];
324324

325325
chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
326-
streamout->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
326+
streamout->ext->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
327327
return 1;
328328
} else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) &&
329329
chunk->msg->expires_at &&

net/sctp/outqueue.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc,
366366
streamout = &asoc->stream.out[chk->sinfo.sinfo_stream];
367367
asoc->sent_cnt_removable--;
368368
asoc->abandoned_sent[SCTP_PR_INDEX(PRIO)]++;
369-
streamout->abandoned_sent[SCTP_PR_INDEX(PRIO)]++;
369+
streamout->ext->abandoned_sent[SCTP_PR_INDEX(PRIO)]++;
370370

371371
if (!chk->tsn_gap_acked) {
372372
if (chk->transport)
@@ -404,7 +404,7 @@ static int sctp_prsctp_prune_unsent(struct sctp_association *asoc,
404404
struct sctp_stream_out *streamout =
405405
&asoc->stream.out[chk->sinfo.sinfo_stream];
406406

407-
streamout->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++;
407+
streamout->ext->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++;
408408
}
409409

410410
msg_len -= SCTP_DATA_SNDSIZE(chk) +

net/sctp/socket.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1927,6 +1927,13 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
19271927
goto out_free;
19281928
}
19291929

1930+
/* Allocate sctp_stream_out_ext if not already done */
1931+
if (unlikely(!asoc->stream.out[sinfo->sinfo_stream].ext)) {
1932+
err = sctp_stream_init_ext(&asoc->stream, sinfo->sinfo_stream);
1933+
if (err)
1934+
goto out_free;
1935+
}
1936+
19301937
if (sctp_wspace(asoc) < msg_len)
19311938
sctp_prsctp_prune(asoc, sinfo, msg_len - sctp_wspace(asoc));
19321939

@@ -6645,7 +6652,7 @@ static int sctp_getsockopt_pr_streamstatus(struct sock *sk, int len,
66456652
char __user *optval,
66466653
int __user *optlen)
66476654
{
6648-
struct sctp_stream_out *streamout;
6655+
struct sctp_stream_out_ext *streamoute;
66496656
struct sctp_association *asoc;
66506657
struct sctp_prstatus params;
66516658
int retval = -EINVAL;
@@ -6668,21 +6675,29 @@ static int sctp_getsockopt_pr_streamstatus(struct sock *sk, int len,
66686675
if (!asoc || params.sprstat_sid >= asoc->stream.outcnt)
66696676
goto out;
66706677

6671-
streamout = &asoc->stream.out[params.sprstat_sid];
6678+
streamoute = asoc->stream.out[params.sprstat_sid].ext;
6679+
if (!streamoute) {
6680+
/* Not allocated yet, means all stats are 0 */
6681+
params.sprstat_abandoned_unsent = 0;
6682+
params.sprstat_abandoned_sent = 0;
6683+
retval = 0;
6684+
goto out;
6685+
}
6686+
66726687
if (policy == SCTP_PR_SCTP_NONE) {
66736688
params.sprstat_abandoned_unsent = 0;
66746689
params.sprstat_abandoned_sent = 0;
66756690
for (policy = 0; policy <= SCTP_PR_INDEX(MAX); policy++) {
66766691
params.sprstat_abandoned_unsent +=
6677-
streamout->abandoned_unsent[policy];
6692+
streamoute->abandoned_unsent[policy];
66786693
params.sprstat_abandoned_sent +=
6679-
streamout->abandoned_sent[policy];
6694+
streamoute->abandoned_sent[policy];
66806695
}
66816696
} else {
66826697
params.sprstat_abandoned_unsent =
6683-
streamout->abandoned_unsent[__SCTP_PR_INDEX(policy)];
6698+
streamoute->abandoned_unsent[__SCTP_PR_INDEX(policy)];
66846699
params.sprstat_abandoned_sent =
6685-
streamout->abandoned_sent[__SCTP_PR_INDEX(policy)];
6700+
streamoute->abandoned_sent[__SCTP_PR_INDEX(policy)];
66866701
}
66876702

66886703
if (put_user(len, optlen) || copy_to_user(optval, &params, len)) {

net/sctp/stream.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,24 @@ int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
121121
return 0;
122122
}
123123

124+
int sctp_stream_init_ext(struct sctp_stream *stream, __u16 sid)
125+
{
126+
struct sctp_stream_out_ext *soute;
127+
128+
soute = kzalloc(sizeof(*soute), GFP_KERNEL);
129+
if (!soute)
130+
return -ENOMEM;
131+
stream->out[sid].ext = soute;
132+
133+
return 0;
134+
}
135+
124136
void sctp_stream_free(struct sctp_stream *stream)
125137
{
138+
int i;
139+
140+
for (i = 0; i < stream->outcnt; i++)
141+
kfree(stream->out[i].ext);
126142
kfree(stream->out);
127143
kfree(stream->in);
128144
}

0 commit comments

Comments
 (0)