aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorHideo Aoki <haoki@redhat.com>2007-12-31 03:11:19 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:00:18 -0500
commit3ab224be6d69de912ee21302745ea45a99274dbc (patch)
tree335dcef1cfacfefe3f36c21d5f144e011bc3bfba /net/core
parenta06b494b61de44617dd58612164bdde56fca7bfb (diff)
[NET] CORE: Introducing new memory accounting interface.
This patch introduces new memory accounting functions for each network protocol. Most of them are renamed from memory accounting functions for stream protocols. At the same time, some stream memory accounting functions are removed since other functions do same thing. Renaming: sk_stream_free_skb() -> sk_wmem_free_skb() __sk_stream_mem_reclaim() -> __sk_mem_reclaim() sk_stream_mem_reclaim() -> sk_mem_reclaim() sk_stream_mem_schedule -> __sk_mem_schedule() sk_stream_pages() -> sk_mem_pages() sk_stream_rmem_schedule() -> sk_rmem_schedule() sk_stream_wmem_schedule() -> sk_wmem_schedule() sk_charge_skb() -> sk_mem_charge() Removeing sk_stream_rfree(): consolidates into sock_rfree() sk_stream_set_owner_r(): consolidates into skb_set_owner_r() sk_stream_mem_schedule() The following functions are added. sk_has_account(): check if the protocol supports accounting sk_mem_uncharge(): do the opposite of sk_mem_charge() In addition, to achieve consolidation, updating sk_wmem_queued is removed from sk_mem_charge(). Next, to consolidate memory accounting functions, this patch adds memory accounting calls to network core functions. Moreover, present memory accounting call is renamed to new accounting call. Finally we replace present memory accounting calls with new interface in TCP and SCTP. Signed-off-by: Takahiro Yasui <tyasui@redhat.com> Signed-off-by: Hideo Aoki <haoki@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/datagram.c2
-rw-r--r--net/core/sock.c104
-rw-r--r--net/core/stream.c84
3 files changed, 107 insertions, 83 deletions
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 2d733131d7ce..8a28fc93b724 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -209,6 +209,7 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags,
209void skb_free_datagram(struct sock *sk, struct sk_buff *skb) 209void skb_free_datagram(struct sock *sk, struct sk_buff *skb)
210{ 210{
211 kfree_skb(skb); 211 kfree_skb(skb);
212 sk_mem_reclaim(sk);
212} 213}
213 214
214/** 215/**
@@ -248,6 +249,7 @@ int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
248 } 249 }
249 250
250 kfree_skb(skb); 251 kfree_skb(skb);
252 sk_mem_reclaim(sk);
251 return err; 253 return err;
252} 254}
253 255
diff --git a/net/core/sock.c b/net/core/sock.c
index 118214047ed2..8c184c4a3811 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -282,6 +282,11 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
282 if (err) 282 if (err)
283 goto out; 283 goto out;
284 284
285 if (!sk_rmem_schedule(sk, skb->truesize)) {
286 err = -ENOBUFS;
287 goto out;
288 }
289
285 skb->dev = NULL; 290 skb->dev = NULL;
286 skb_set_owner_r(skb, sk); 291 skb_set_owner_r(skb, sk);
287 292
@@ -1107,7 +1112,9 @@ void sock_rfree(struct sk_buff *skb)
1107{ 1112{
1108 struct sock *sk = skb->sk; 1113 struct sock *sk = skb->sk;
1109 1114
1115 skb_truesize_check(skb);
1110 atomic_sub(skb->truesize, &sk->sk_rmem_alloc); 1116 atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
1117 sk_mem_uncharge(skb->sk, skb->truesize);
1111} 1118}
1112 1119
1113 1120
@@ -1384,6 +1391,103 @@ int sk_wait_data(struct sock *sk, long *timeo)
1384 1391
1385EXPORT_SYMBOL(sk_wait_data); 1392EXPORT_SYMBOL(sk_wait_data);
1386 1393
1394/**
1395 * __sk_mem_schedule - increase sk_forward_alloc and memory_allocated
1396 * @sk: socket
1397 * @size: memory size to allocate
1398 * @kind: allocation type
1399 *
1400 * If kind is SK_MEM_SEND, it means wmem allocation. Otherwise it means
1401 * rmem allocation. This function assumes that protocols which have
1402 * memory_pressure use sk_wmem_queued as write buffer accounting.
1403 */
1404int __sk_mem_schedule(struct sock *sk, int size, int kind)
1405{
1406 struct proto *prot = sk->sk_prot;
1407 int amt = sk_mem_pages(size);
1408 int allocated;
1409
1410 sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
1411 allocated = atomic_add_return(amt, prot->memory_allocated);
1412
1413 /* Under limit. */
1414 if (allocated <= prot->sysctl_mem[0]) {
1415 if (prot->memory_pressure && *prot->memory_pressure)
1416 *prot->memory_pressure = 0;
1417 return 1;
1418 }
1419
1420 /* Under pressure. */
1421 if (allocated > prot->sysctl_mem[1])
1422 if (prot->enter_memory_pressure)
1423 prot->enter_memory_pressure();
1424
1425 /* Over hard limit. */
1426 if (allocated > prot->sysctl_mem[2])
1427 goto suppress_allocation;
1428
1429 /* guarantee minimum buffer size under pressure */
1430 if (kind == SK_MEM_RECV) {
1431 if (atomic_read(&sk->sk_rmem_alloc) < prot->sysctl_rmem[0])
1432 return 1;
1433 } else { /* SK_MEM_SEND */
1434 if (sk->sk_type == SOCK_STREAM) {
1435 if (sk->sk_wmem_queued < prot->sysctl_wmem[0])
1436 return 1;
1437 } else if (atomic_read(&sk->sk_wmem_alloc) <
1438 prot->sysctl_wmem[0])
1439 return 1;
1440 }
1441
1442 if (prot->memory_pressure) {
1443 if (!*prot->memory_pressure ||
1444 prot->sysctl_mem[2] > atomic_read(prot->sockets_allocated) *
1445 sk_mem_pages(sk->sk_wmem_queued +
1446 atomic_read(&sk->sk_rmem_alloc) +
1447 sk->sk_forward_alloc))
1448 return 1;
1449 }
1450
1451suppress_allocation:
1452
1453 if (kind == SK_MEM_SEND && sk->sk_type == SOCK_STREAM) {
1454 sk_stream_moderate_sndbuf(sk);
1455
1456 /* Fail only if socket is _under_ its sndbuf.
1457 * In this case we cannot block, so that we have to fail.
1458 */
1459 if (sk->sk_wmem_queued + size >= sk->sk_sndbuf)
1460 return 1;
1461 }
1462
1463 /* Alas. Undo changes. */
1464 sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM;
1465 atomic_sub(amt, prot->memory_allocated);
1466 return 0;
1467}
1468
1469EXPORT_SYMBOL(__sk_mem_schedule);
1470
1471/**
1472 * __sk_reclaim - reclaim memory_allocated
1473 * @sk: socket
1474 */
1475void __sk_mem_reclaim(struct sock *sk)
1476{
1477 struct proto *prot = sk->sk_prot;
1478
1479 atomic_sub(sk->sk_forward_alloc / SK_MEM_QUANTUM,
1480 prot->memory_allocated);
1481 sk->sk_forward_alloc &= SK_MEM_QUANTUM - 1;
1482
1483 if (prot->memory_pressure && *prot->memory_pressure &&
1484 (atomic_read(prot->memory_allocated) < prot->sysctl_mem[0]))
1485 *prot->memory_pressure = 0;
1486}
1487
1488EXPORT_SYMBOL(__sk_mem_reclaim);
1489
1490
1387/* 1491/*
1388 * Set of default routines for initialising struct proto_ops when 1492 * Set of default routines for initialising struct proto_ops when
1389 * the protocol does not support a particular function. In certain 1493 * the protocol does not support a particular function. In certain
diff --git a/net/core/stream.c b/net/core/stream.c
index bf188ffdbdbe..4a0ad152c9c4 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -172,17 +172,6 @@ do_interrupted:
172 172
173EXPORT_SYMBOL(sk_stream_wait_memory); 173EXPORT_SYMBOL(sk_stream_wait_memory);
174 174
175void sk_stream_rfree(struct sk_buff *skb)
176{
177 struct sock *sk = skb->sk;
178
179 skb_truesize_check(skb);
180 atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
181 sk->sk_forward_alloc += skb->truesize;
182}
183
184EXPORT_SYMBOL(sk_stream_rfree);
185
186int sk_stream_error(struct sock *sk, int flags, int err) 175int sk_stream_error(struct sock *sk, int flags, int err)
187{ 176{
188 if (err == -EPIPE) 177 if (err == -EPIPE)
@@ -194,77 +183,6 @@ int sk_stream_error(struct sock *sk, int flags, int err)
194 183
195EXPORT_SYMBOL(sk_stream_error); 184EXPORT_SYMBOL(sk_stream_error);
196 185
197void __sk_stream_mem_reclaim(struct sock *sk)
198{
199 atomic_sub(sk->sk_forward_alloc >> SK_STREAM_MEM_QUANTUM_SHIFT,
200 sk->sk_prot->memory_allocated);
201 sk->sk_forward_alloc &= SK_STREAM_MEM_QUANTUM - 1;
202 if (*sk->sk_prot->memory_pressure &&
203 (atomic_read(sk->sk_prot->memory_allocated) <
204 sk->sk_prot->sysctl_mem[0]))
205 *sk->sk_prot->memory_pressure = 0;
206}
207
208EXPORT_SYMBOL(__sk_stream_mem_reclaim);
209
210int sk_stream_mem_schedule(struct sock *sk, int size, int kind)
211{
212 int amt = sk_stream_pages(size);
213 struct proto *prot = sk->sk_prot;
214
215 sk->sk_forward_alloc += amt * SK_STREAM_MEM_QUANTUM;
216 atomic_add(amt, prot->memory_allocated);
217
218 /* Under limit. */
219 if (atomic_read(prot->memory_allocated) < prot->sysctl_mem[0]) {
220 if (*prot->memory_pressure)
221 *prot->memory_pressure = 0;
222 return 1;
223 }
224
225 /* Over hard limit. */
226 if (atomic_read(prot->memory_allocated) > prot->sysctl_mem[2]) {
227 prot->enter_memory_pressure();
228 goto suppress_allocation;
229 }
230
231 /* Under pressure. */
232 if (atomic_read(prot->memory_allocated) > prot->sysctl_mem[1])
233 prot->enter_memory_pressure();
234
235 if (kind) {
236 if (atomic_read(&sk->sk_rmem_alloc) < prot->sysctl_rmem[0])
237 return 1;
238 } else if (sk->sk_wmem_queued < prot->sysctl_wmem[0])
239 return 1;
240
241 if (!*prot->memory_pressure ||
242 prot->sysctl_mem[2] > atomic_read(prot->sockets_allocated) *
243 sk_stream_pages(sk->sk_wmem_queued +
244 atomic_read(&sk->sk_rmem_alloc) +
245 sk->sk_forward_alloc))
246 return 1;
247
248suppress_allocation:
249
250 if (!kind) {
251 sk_stream_moderate_sndbuf(sk);
252
253 /* Fail only if socket is _under_ its sndbuf.
254 * In this case we cannot block, so that we have to fail.
255 */
256 if (sk->sk_wmem_queued + size >= sk->sk_sndbuf)
257 return 1;
258 }
259
260 /* Alas. Undo changes. */
261 sk->sk_forward_alloc -= amt * SK_STREAM_MEM_QUANTUM;
262 atomic_sub(amt, prot->memory_allocated);
263 return 0;
264}
265
266EXPORT_SYMBOL(sk_stream_mem_schedule);
267
268void sk_stream_kill_queues(struct sock *sk) 186void sk_stream_kill_queues(struct sock *sk)
269{ 187{
270 /* First the read buffer. */ 188 /* First the read buffer. */
@@ -277,7 +195,7 @@ void sk_stream_kill_queues(struct sock *sk)
277 BUG_TRAP(skb_queue_empty(&sk->sk_write_queue)); 195 BUG_TRAP(skb_queue_empty(&sk->sk_write_queue));
278 196
279 /* Account for returned memory. */ 197 /* Account for returned memory. */
280 sk_stream_mem_reclaim(sk); 198 sk_mem_reclaim(sk);
281 199
282 BUG_TRAP(!sk->sk_wmem_queued); 200 BUG_TRAP(!sk->sk_wmem_queued);
283 BUG_TRAP(!sk->sk_forward_alloc); 201 BUG_TRAP(!sk->sk_forward_alloc);