aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r--net/sctp/socket.c69
1 files changed, 57 insertions, 12 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 772fbfb4bfda..b9952425c79a 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -107,23 +107,42 @@ static void sctp_sock_migrate(struct sock *, struct sock *,
107 struct sctp_association *, sctp_socket_type_t); 107 struct sctp_association *, sctp_socket_type_t);
108static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; 108static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
109 109
110extern struct kmem_cache *sctp_bucket_cachep;
111extern int sysctl_sctp_mem[3];
112extern int sysctl_sctp_rmem[3];
113extern int sysctl_sctp_wmem[3];
114
115int sctp_memory_pressure;
116atomic_t sctp_memory_allocated;
117atomic_t sctp_sockets_allocated;
118
119static void sctp_enter_memory_pressure(void)
120{
121 sctp_memory_pressure = 1;
122}
123
124
110/* Get the sndbuf space available at the time on the association. */ 125/* Get the sndbuf space available at the time on the association. */
111static inline int sctp_wspace(struct sctp_association *asoc) 126static inline int sctp_wspace(struct sctp_association *asoc)
112{ 127{
113 struct sock *sk = asoc->base.sk; 128 int amt;
114 int amt = 0;
115 129
116 if (asoc->ep->sndbuf_policy) { 130 if (asoc->ep->sndbuf_policy)
117 /* make sure that no association uses more than sk_sndbuf */ 131 amt = asoc->sndbuf_used;
118 amt = sk->sk_sndbuf - asoc->sndbuf_used; 132 else
133 amt = atomic_read(&asoc->base.sk->sk_wmem_alloc);
134
135 if (amt >= asoc->base.sk->sk_sndbuf) {
136 if (asoc->base.sk->sk_userlocks & SOCK_SNDBUF_LOCK)
137 amt = 0;
138 else {
139 amt = sk_stream_wspace(asoc->base.sk);
140 if (amt < 0)
141 amt = 0;
142 }
119 } else { 143 } else {
120 /* do socket level accounting */ 144 amt = asoc->base.sk->sk_sndbuf - amt;
121 amt = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
122 } 145 }
123
124 if (amt < 0)
125 amt = 0;
126
127 return amt; 146 return amt;
128} 147}
129 148
@@ -155,6 +174,7 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
155 sizeof(struct sctp_chunk); 174 sizeof(struct sctp_chunk);
156 175
157 atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); 176 atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
177 sk_charge_skb(sk, chunk->skb);
158} 178}
159 179
160/* Verify that this is a valid address. */ 180/* Verify that this is a valid address. */
@@ -3293,6 +3313,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
3293 sp->hmac = NULL; 3313 sp->hmac = NULL;
3294 3314
3295 SCTP_DBG_OBJCNT_INC(sock); 3315 SCTP_DBG_OBJCNT_INC(sock);
3316 atomic_inc(&sctp_sockets_allocated);
3296 return 0; 3317 return 0;
3297} 3318}
3298 3319
@@ -3306,7 +3327,7 @@ SCTP_STATIC int sctp_destroy_sock(struct sock *sk)
3306 /* Release our hold on the endpoint. */ 3327 /* Release our hold on the endpoint. */
3307 ep = sctp_sk(sk)->ep; 3328 ep = sctp_sk(sk)->ep;
3308 sctp_endpoint_free(ep); 3329 sctp_endpoint_free(ep);
3309 3330 atomic_dec(&sctp_sockets_allocated);
3310 return 0; 3331 return 0;
3311} 3332}
3312 3333
@@ -5720,6 +5741,12 @@ static void sctp_wfree(struct sk_buff *skb)
5720 5741
5721 atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); 5742 atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
5722 5743
5744 /*
5745 * This undoes what is done via sk_charge_skb
5746 */
5747 sk->sk_wmem_queued -= skb->truesize;
5748 sk->sk_forward_alloc += skb->truesize;
5749
5723 sock_wfree(skb); 5750 sock_wfree(skb);
5724 __sctp_write_space(asoc); 5751 __sctp_write_space(asoc);
5725 5752
@@ -5737,6 +5764,11 @@ void sctp_sock_rfree(struct sk_buff *skb)
5737 struct sctp_ulpevent *event = sctp_skb2event(skb); 5764 struct sctp_ulpevent *event = sctp_skb2event(skb);
5738 5765
5739 atomic_sub(event->rmem_len, &sk->sk_rmem_alloc); 5766 atomic_sub(event->rmem_len, &sk->sk_rmem_alloc);
5767
5768 /*
5769 * Mimic the behavior of sk_stream_rfree
5770 */
5771 sk->sk_forward_alloc += event->rmem_len;
5740} 5772}
5741 5773
5742 5774
@@ -6126,6 +6158,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
6126 sctp_release_sock(newsk); 6158 sctp_release_sock(newsk);
6127} 6159}
6128 6160
6161
6129/* This proto struct describes the ULP interface for SCTP. */ 6162/* This proto struct describes the ULP interface for SCTP. */
6130struct proto sctp_prot = { 6163struct proto sctp_prot = {
6131 .name = "SCTP", 6164 .name = "SCTP",
@@ -6148,6 +6181,12 @@ struct proto sctp_prot = {
6148 .unhash = sctp_unhash, 6181 .unhash = sctp_unhash,
6149 .get_port = sctp_get_port, 6182 .get_port = sctp_get_port,
6150 .obj_size = sizeof(struct sctp_sock), 6183 .obj_size = sizeof(struct sctp_sock),
6184 .sysctl_mem = sysctl_sctp_mem,
6185 .sysctl_rmem = sysctl_sctp_rmem,
6186 .sysctl_wmem = sysctl_sctp_wmem,
6187 .memory_pressure = &sctp_memory_pressure,
6188 .enter_memory_pressure = sctp_enter_memory_pressure,
6189 .memory_allocated = &sctp_memory_allocated,
6151}; 6190};
6152 6191
6153#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 6192#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -6172,5 +6211,11 @@ struct proto sctpv6_prot = {
6172 .unhash = sctp_unhash, 6211 .unhash = sctp_unhash,
6173 .get_port = sctp_get_port, 6212 .get_port = sctp_get_port,
6174 .obj_size = sizeof(struct sctp6_sock), 6213 .obj_size = sizeof(struct sctp6_sock),
6214 .sysctl_mem = sysctl_sctp_mem,
6215 .sysctl_rmem = sysctl_sctp_rmem,
6216 .sysctl_wmem = sysctl_sctp_wmem,
6217 .memory_pressure = &sctp_memory_pressure,
6218 .enter_memory_pressure = sctp_enter_memory_pressure,
6219 .memory_allocated = &sctp_memory_allocated,
6175}; 6220};
6176#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ 6221#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */