diff options
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 69 |
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); |
108 | static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; | 108 | static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; |
109 | 109 | ||
110 | extern struct kmem_cache *sctp_bucket_cachep; | ||
111 | extern int sysctl_sctp_mem[3]; | ||
112 | extern int sysctl_sctp_rmem[3]; | ||
113 | extern int sysctl_sctp_wmem[3]; | ||
114 | |||
115 | int sctp_memory_pressure; | ||
116 | atomic_t sctp_memory_allocated; | ||
117 | atomic_t sctp_sockets_allocated; | ||
118 | |||
119 | static 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. */ |
111 | static inline int sctp_wspace(struct sctp_association *asoc) | 126 | static 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. */ |
6130 | struct proto sctp_prot = { | 6163 | struct 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) */ |