Skip to content

Commit cea8768

Browse files
marceloleitnerdavem330
authored andcommitted
sctp: allow sctp_transmit_packet and others to use gfp
Currently sctp_sendmsg() triggers some calls that will allocate memory with GFP_ATOMIC even when not necessary. In the case of sctp_packet_transmit it will allocate a linear skb that will be used to construct the packet and this may cause sends to fail due to ENOMEM more often than anticipated specially with big MTUs. This patch thus allows it to inherit gfp flags from upper calls so that it can use GFP_KERNEL if it was triggered by a sctp_sendmsg call or similar. All others, like retransmits or flushes started from BH, are still allocated using GFP_ATOMIC. In netperf tests this didn't result in any performance drawbacks when memory is not too fragmented and made it trigger ENOMEM way less often. Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 6f15cdb commit cea8768

File tree

9 files changed

+89
-72
lines changed

9 files changed

+89
-72
lines changed

include/net/sctp/sm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ struct sctp_chunk *sctp_make_cwr(const struct sctp_association *,
201201
struct sctp_chunk * sctp_make_datafrag_empty(struct sctp_association *,
202202
const struct sctp_sndrcvinfo *sinfo,
203203
int len, const __u8 flags,
204-
__u16 ssn);
204+
__u16 ssn, gfp_t gfp);
205205
struct sctp_chunk *sctp_make_ecne(const struct sctp_association *,
206206
const __u32);
207207
struct sctp_chunk *sctp_make_sack(const struct sctp_association *);

include/net/sctp/structs.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ void sctp_chunk_free(struct sctp_chunk *);
655655
void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data);
656656
struct sctp_chunk *sctp_chunkify(struct sk_buff *,
657657
const struct sctp_association *,
658-
struct sock *);
658+
struct sock *, gfp_t gfp);
659659
void sctp_init_addrs(struct sctp_chunk *, union sctp_addr *,
660660
union sctp_addr *);
661661
const union sctp_addr *sctp_source(const struct sctp_chunk *chunk);
@@ -717,10 +717,10 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *,
717717
__u16 sport, __u16 dport);
718718
struct sctp_packet *sctp_packet_config(struct sctp_packet *, __u32 vtag, int);
719719
sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *,
720-
struct sctp_chunk *, int);
720+
struct sctp_chunk *, int, gfp_t);
721721
sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *,
722722
struct sctp_chunk *);
723-
int sctp_packet_transmit(struct sctp_packet *);
723+
int sctp_packet_transmit(struct sctp_packet *, gfp_t);
724724
void sctp_packet_free(struct sctp_packet *);
725725

726726
static inline int sctp_packet_empty(struct sctp_packet *packet)
@@ -1053,15 +1053,15 @@ struct sctp_outq {
10531053
void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
10541054
void sctp_outq_teardown(struct sctp_outq *);
10551055
void sctp_outq_free(struct sctp_outq*);
1056-
int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk);
1056+
int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk, gfp_t);
10571057
int sctp_outq_sack(struct sctp_outq *, struct sctp_chunk *);
10581058
int sctp_outq_is_empty(const struct sctp_outq *);
10591059
void sctp_outq_restart(struct sctp_outq *);
10601060

10611061
void sctp_retransmit(struct sctp_outq *, struct sctp_transport *,
10621062
sctp_retransmit_reason_t);
10631063
void sctp_retransmit_mark(struct sctp_outq *, struct sctp_transport *, __u8);
1064-
int sctp_outq_uncork(struct sctp_outq *);
1064+
int sctp_outq_uncork(struct sctp_outq *, gfp_t gfp);
10651065
/* Uncork and flush an outqueue. */
10661066
static inline void sctp_outq_cork(struct sctp_outq *q)
10671067
{

net/sctp/associola.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1493,7 +1493,7 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len)
14931493

14941494
asoc->peer.sack_needed = 0;
14951495

1496-
sctp_outq_tail(&asoc->outqueue, sack);
1496+
sctp_outq_tail(&asoc->outqueue, sack, GFP_ATOMIC);
14971497

14981498
/* Stop the SACK timer. */
14991499
timer = &asoc->timers[SCTP_EVENT_TIMEOUT_SACK];

net/sctp/chunk.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
260260
frag |= SCTP_DATA_SACK_IMM;
261261
}
262262

263-
chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
263+
chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag,
264+
0, GFP_KERNEL);
264265

265266
if (!chunk) {
266267
err = -ENOMEM;
@@ -296,7 +297,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
296297
(sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY))
297298
frag |= SCTP_DATA_SACK_IMM;
298299

299-
chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
300+
chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag,
301+
0, GFP_KERNEL);
300302

301303
if (!chunk) {
302304
err = -ENOMEM;

net/sctp/input.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ int sctp_rcv(struct sk_buff *skb)
221221
goto discard_release;
222222

223223
/* Create an SCTP packet structure. */
224-
chunk = sctp_chunkify(skb, asoc, sk);
224+
chunk = sctp_chunkify(skb, asoc, sk, GFP_ATOMIC);
225225
if (!chunk)
226226
goto discard_release;
227227
SCTP_INPUT_CB(skb)->chunk = chunk;

net/sctp/output.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ void sctp_packet_free(struct sctp_packet *packet)
153153
*/
154154
sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet,
155155
struct sctp_chunk *chunk,
156-
int one_packet)
156+
int one_packet, gfp_t gfp)
157157
{
158158
sctp_xmit_t retval;
159159
int error = 0;
@@ -163,7 +163,7 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet,
163163
switch ((retval = (sctp_packet_append_chunk(packet, chunk)))) {
164164
case SCTP_XMIT_PMTU_FULL:
165165
if (!packet->has_cookie_echo) {
166-
error = sctp_packet_transmit(packet);
166+
error = sctp_packet_transmit(packet, gfp);
167167
if (error < 0)
168168
chunk->skb->sk->sk_err = -error;
169169

@@ -376,7 +376,7 @@ static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk)
376376
*
377377
* The return value is a normal kernel error return value.
378378
*/
379-
int sctp_packet_transmit(struct sctp_packet *packet)
379+
int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
380380
{
381381
struct sctp_transport *tp = packet->transport;
382382
struct sctp_association *asoc = tp->asoc;

net/sctp/outqueue.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static void sctp_mark_missing(struct sctp_outq *q,
6868

6969
static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 sack_ctsn);
7070

71-
static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout);
71+
static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp);
7272

7373
/* Add data to the front of the queue. */
7474
static inline void sctp_outq_head_data(struct sctp_outq *q,
@@ -285,7 +285,7 @@ void sctp_outq_free(struct sctp_outq *q)
285285
}
286286

287287
/* Put a new chunk in an sctp_outq. */
288-
int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
288+
int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk, gfp_t gfp)
289289
{
290290
struct net *net = sock_net(q->asoc->base.sk);
291291
int error = 0;
@@ -341,7 +341,7 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
341341
return error;
342342

343343
if (!q->cork)
344-
error = sctp_outq_flush(q, 0);
344+
error = sctp_outq_flush(q, 0, gfp);
345345

346346
return error;
347347
}
@@ -510,7 +510,7 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
510510
* will be flushed at the end.
511511
*/
512512
if (reason != SCTP_RTXR_FAST_RTX)
513-
error = sctp_outq_flush(q, /* rtx_timeout */ 1);
513+
error = sctp_outq_flush(q, /* rtx_timeout */ 1, GFP_ATOMIC);
514514

515515
if (error)
516516
q->asoc->base.sk->sk_err = -error;
@@ -601,12 +601,12 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
601601
* control chunks are already freed so there
602602
* is nothing we can do.
603603
*/
604-
sctp_packet_transmit(pkt);
604+
sctp_packet_transmit(pkt, GFP_ATOMIC);
605605
goto redo;
606606
}
607607

608608
/* Send this packet. */
609-
error = sctp_packet_transmit(pkt);
609+
error = sctp_packet_transmit(pkt, GFP_ATOMIC);
610610

611611
/* If we are retransmitting, we should only
612612
* send a single packet.
@@ -622,7 +622,7 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
622622

623623
case SCTP_XMIT_RWND_FULL:
624624
/* Send this packet. */
625-
error = sctp_packet_transmit(pkt);
625+
error = sctp_packet_transmit(pkt, GFP_ATOMIC);
626626

627627
/* Stop sending DATA as there is no more room
628628
* at the receiver.
@@ -632,7 +632,7 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
632632

633633
case SCTP_XMIT_DELAY:
634634
/* Send this packet. */
635-
error = sctp_packet_transmit(pkt);
635+
error = sctp_packet_transmit(pkt, GFP_ATOMIC);
636636

637637
/* Stop sending DATA because of nagle delay. */
638638
done = 1;
@@ -685,12 +685,12 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
685685
}
686686

687687
/* Cork the outqueue so queued chunks are really queued. */
688-
int sctp_outq_uncork(struct sctp_outq *q)
688+
int sctp_outq_uncork(struct sctp_outq *q, gfp_t gfp)
689689
{
690690
if (q->cork)
691691
q->cork = 0;
692692

693-
return sctp_outq_flush(q, 0);
693+
return sctp_outq_flush(q, 0, gfp);
694694
}
695695

696696

@@ -703,7 +703,7 @@ int sctp_outq_uncork(struct sctp_outq *q)
703703
* locking concerns must be made. Today we use the sock lock to protect
704704
* this function.
705705
*/
706-
static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
706+
static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
707707
{
708708
struct sctp_packet *packet;
709709
struct sctp_packet singleton;
@@ -825,7 +825,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
825825
sctp_packet_init(&singleton, transport, sport, dport);
826826
sctp_packet_config(&singleton, vtag, 0);
827827
sctp_packet_append_chunk(&singleton, chunk);
828-
error = sctp_packet_transmit(&singleton);
828+
error = sctp_packet_transmit(&singleton, gfp);
829829
if (error < 0)
830830
return error;
831831
break;
@@ -856,7 +856,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
856856
case SCTP_CID_ASCONF:
857857
case SCTP_CID_FWD_TSN:
858858
status = sctp_packet_transmit_chunk(packet, chunk,
859-
one_packet);
859+
one_packet, gfp);
860860
if (status != SCTP_XMIT_OK) {
861861
/* put the chunk back */
862862
list_add(&chunk->list, &q->control_chunk_list);
@@ -1011,7 +1011,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
10111011
atomic_read(&chunk->skb->users) : -1);
10121012

10131013
/* Add the chunk to the packet. */
1014-
status = sctp_packet_transmit_chunk(packet, chunk, 0);
1014+
status = sctp_packet_transmit_chunk(packet, chunk, 0, gfp);
10151015

10161016
switch (status) {
10171017
case SCTP_XMIT_PMTU_FULL:
@@ -1088,7 +1088,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
10881088
send_ready);
10891089
packet = &t->packet;
10901090
if (!sctp_packet_empty(packet))
1091-
error = sctp_packet_transmit(packet);
1091+
error = sctp_packet_transmit(packet, gfp);
10921092

10931093
/* Clear the burst limited state, if any */
10941094
sctp_transport_burst_reset(t);

0 commit comments

Comments
 (0)