From: Hideo AOKI <haoki@redhat.com>
To: David Miller <davem@davemloft.net>,
Herbert Xu <herbert@gondor.apana.org.au>,
netdev <netdev@vger.kernel.org>
Cc: Takahiro Yasui <tyasui@redhat.com>,
Masami Hiramatsu <mhiramat@redhat.com>,
Satoshi Oshima <satoshi.oshima.fk@hitachi.com>,
billfink@mindspring.com, Andi Kleen <andi@firstfloor.org>,
Evgeniy Polyakov <johnpol@2ka.mipt.ru>,
Stephen Hemminger <shemminger@linux-foundation.org>,
yoshfuji@linux-ipv6.org,
Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
haoki@redhat.com
Subject: [PATCH 4/4] [UDP]: memory accounting in IPv4
Date: Sat, 15 Dec 2007 00:15:34 -0500 [thread overview]
Message-ID: <476362F6.1030700@redhat.com> (raw)
In-Reply-To: <47636120.4050701@redhat.com>
This patch adds UDP memory usage accounting in IPv4.
Send buffer accounting is performed by IP layer, because skbuff is
allocated in the layer.
Receive buffer is charged, when the buffer successfully received.
Destructor of the buffer does un charging and reclaiming, when the
buffer is freed. To set destructor at proper place, we introduce
udp_set_owner_r().
In addition, to make sure that sk_forward_alloc is totally uncharged
in socket destruction, a reclaiming is added to inet_sock_destruct().
Cc: Satoshi Oshima <satoshi.oshima.fk@hitachi.com>
signed-off-by: Takahiro Yasui <tyasui@redhat.com>
signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
signed-off-by: Hideo Aoki <haoki@redhat.com>
---
af_inet.c | 2 ++
ip_output.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
udp.c | 16 +++++++++++++++-
3 files changed, 61 insertions(+), 3 deletions(-)
diff -pruN net-2.6-udp-take10a4-p3/net/ipv4/af_inet.c net-2.6-udp-take10a4-p4/net/ipv4/af_inet.c
--- net-2.6-udp-take10a4-p3/net/ipv4/af_inet.c 2007-12-14 20:27:54.000000000 -0500
+++ net-2.6-udp-take10a4-p4/net/ipv4/af_inet.c 2007-12-14 21:06:54.000000000 -0500
@@ -144,6 +144,8 @@ void inet_sock_destruct(struct sock *sk)
printk("Attempt to release alive inet socket %p\n", sk);
return;
}
+ if (sk->sk_type == SOCK_DGRAM)
+ sk_datagram_mem_reclaim(sk);
BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
diff -pruN net-2.6-udp-take10a4-p3/net/ipv4/ip_output.c net-2.6-udp-take10a4-p4/net/ipv4/ip_output.c
--- net-2.6-udp-take10a4-p3/net/ipv4/ip_output.c 2007-12-14 16:42:04.000000000 -0500
+++ net-2.6-udp-take10a4-p4/net/ipv4/ip_output.c 2007-12-14 21:06:54.000000000 -0500
@@ -707,6 +707,7 @@ static inline int ip_ufo_append_data(str
{
struct sk_buff *skb;
int err;
+ int first_size, second_size;
/* There is support for UDP fragmentation offload by network
* device, so create one single skb packet containing complete
@@ -720,6 +721,11 @@ static inline int ip_ufo_append_data(str
if (skb == NULL)
return err;
+ if (!sk_account_wmem_charge(sk, skb->truesize)) {
+ err = -ENOBUFS;
+ goto fail;
+ }
+
/* reserve space for Hardware header */
skb_reserve(skb, hh_len);
@@ -736,6 +742,7 @@ static inline int ip_ufo_append_data(str
skb->csum = 0;
sk->sk_sndmsg_off = 0;
}
+ first_size = skb->truesize;
err = skb_append_datato_frags(sk,skb, getfrag, from,
(length - transhdrlen));
@@ -743,6 +750,15 @@ static inline int ip_ufo_append_data(str
/* specify the length of each IP datagram fragment*/
skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+
+ second_size = skb->truesize - first_size;
+ if (!sk_account_wmem_charge(sk, second_size)) {
+ sk_account_uncharge(sk, first_size);
+ sk_mem_reclaim(sk);
+ err = -ENOBUFS;
+ goto fail;
+ }
+
__skb_queue_tail(&sk->sk_write_queue, skb);
return 0;
@@ -750,6 +766,7 @@ static inline int ip_ufo_append_data(str
/* There is not enough support do UFO ,
* so follow normal path
*/
+fail:
kfree_skb(skb);
return err;
}
@@ -924,6 +941,11 @@ alloc_new_skb:
}
if (skb == NULL)
goto error;
+ if (!sk_account_wmem_charge(sk, skb->truesize)) {
+ err = -ENOBUFS;
+ kfree_skb(skb);
+ goto error;
+ }
/*
* Fill in the control structures
@@ -954,6 +976,8 @@ alloc_new_skb:
copy = datalen - transhdrlen - fraggap;
if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
err = -EFAULT;
+ sk_account_uncharge(sk, skb->truesize);
+ sk_mem_reclaim(sk);
kfree_skb(skb);
goto error;
}
@@ -1023,6 +1047,10 @@ alloc_new_skb:
frag = &skb_shinfo(skb)->frags[i];
skb->truesize += PAGE_SIZE;
atomic_add(PAGE_SIZE, &sk->sk_wmem_alloc);
+ if (!sk_account_wmem_charge(sk, PAGE_SIZE)) {
+ err = -ENOBUFS;
+ goto error;
+ }
} else {
err = -EMSGSIZE;
goto error;
@@ -1124,6 +1152,11 @@ ssize_t ip_append_page(struct sock *sk,
err = -ENOBUFS;
goto error;
}
+ if (!sk_account_wmem_charge(sk, skb->truesize)) {
+ kfree_skb(skb);
+ err = -ENOBUFS;
+ goto error;
+ }
/*
* Fill in the control structures
@@ -1213,13 +1246,14 @@ int ip_push_pending_frames(struct sock *
struct iphdr *iph;
__be16 df = 0;
__u8 ttl;
- int err = 0;
+ int err = 0, send_size;
if ((skb = __skb_dequeue(&sk->sk_write_queue)) == NULL)
goto out;
tail_skb = &(skb_shinfo(skb)->frag_list);
/* move skb->data to ip header from ext header */
+ send_size = skb->truesize;
if (skb->data < skb_network_header(skb))
__skb_pull(skb, skb_network_offset(skb));
while ((tmp_skb = __skb_dequeue(&sk->sk_write_queue)) != NULL) {
@@ -1229,6 +1263,7 @@ int ip_push_pending_frames(struct sock *
skb->len += tmp_skb->len;
skb->data_len += tmp_skb->len;
skb->truesize += tmp_skb->truesize;
+ send_size += tmp_skb->truesize;
__sock_put(tmp_skb->sk);
tmp_skb->destructor = NULL;
tmp_skb->sk = NULL;
@@ -1284,6 +1319,8 @@ int ip_push_pending_frames(struct sock *
/* Netfilter gets whole the not fragmented skb. */
err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
skb->dst->dev, dst_output);
+ sk_account_uncharge(sk, send_size);
+ sk_mem_reclaim(sk);
if (err) {
if (err > 0)
err = inet->recverr ? net_xmit_errno(err) : 0;
@@ -1306,10 +1343,15 @@ error:
void ip_flush_pending_frames(struct sock *sk)
{
struct sk_buff *skb;
+ int truesize = 0;
- while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL)
+ while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) {
+ truesize += skb->truesize;
kfree_skb(skb);
+ }
+ sk_account_uncharge(sk, truesize);
+ sk_mem_reclaim(sk);
ip_cork_release(inet_sk(sk));
}
diff -pruN net-2.6-udp-take10a4-p3/net/ipv4/udp.c net-2.6-udp-take10a4-p4/net/ipv4/udp.c
--- net-2.6-udp-take10a4-p3/net/ipv4/udp.c 2007-12-14 20:27:54.000000000 -0500
+++ net-2.6-udp-take10a4-p4/net/ipv4/udp.c 2007-12-14 21:06:54.000000000 -0500
@@ -934,6 +934,13 @@ int udp_disconnect(struct sock *sk, int
return 0;
}
+void udp_set_owner_r(struct sk_buff *skb, struct sock *sk)
+{
+ skb->sk = sk;
+ skb->destructor = sk_datagram_rfree;
+ atomic_add(skb->truesize, &sk->sk_rmem_alloc);
+}
+
/* returns:
* -1: error
* 0: success
@@ -1022,10 +1029,17 @@ int udp_queue_rcv_skb(struct sock * sk,
goto drop;
}
- if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {
+ if (!sk_account_rmem_charge(sk, skb->truesize)) {
+ UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, up->pcflag);
+ goto drop;
+ }
+
+ if ((rc = sock_queue_rcv_skb_with_owner(sk, skb, udp_set_owner_r)) < 0) {
/* Note that an ENOMEM error is charged twice */
if (rc == -ENOMEM)
UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, up->pcflag);
+ sk_account_uncharge(sk, skb->truesize);
+ sk_datagram_mem_reclaim(sk);
goto drop;
}
--
Hitachi Computer Products (America) Inc.
next prev parent reply other threads:[~2007-12-15 5:22 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-12-15 5:07 [PATCH 0/4] [UDP]: memory accounting and limitation (take 10) Hideo AOKI
2007-12-15 5:14 ` [PATCH 1/4] [UDP]: fix send buffer check Hideo AOKI
2007-12-15 5:15 ` [PATCH 2/4] [CORE]: datagram: mem_scheudle functions Hideo AOKI
2007-12-15 15:32 ` Herbert Xu
2007-12-16 21:20 ` Hideo AOKI
2007-12-15 5:15 ` [PATCH 3/4] [UDP]: add udp_mem, udp_rmem_min and udp_wmem_min Hideo AOKI
2007-12-15 5:15 ` Hideo AOKI [this message]
2007-12-16 5:34 ` [PATCH 0/4] [UDP]: memory accounting and limitation (take 10) David Miller
2007-12-16 21:21 ` Hideo AOKI
-- strict thread matches above, loose matches on Subject: below --
2007-12-18 2:33 [PATCH 0/4] [UDP]: memory accounting and limitation (take 11) Hideo AOKI
2007-12-18 2:38 ` [PATCH 4/4] [UDP]: memory accounting in IPv4 Hideo AOKI
2007-12-20 11:44 ` David Miller
2007-12-21 3:58 ` Hideo AOKI
2007-11-28 18:48 [PATCH 0/4] UDP memory accounting and limitation (take 9) Hideo AOKI
2007-11-28 18:53 ` [PATCH 4/4] udp: memory accounting in IPv4 Hideo AOKI
2007-12-01 12:21 ` Herbert Xu
2007-12-01 13:08 ` Eric Dumazet
2007-12-01 13:16 ` Herbert Xu
2007-12-04 0:14 ` Hideo AOKI
2007-12-04 0:26 ` Herbert Xu
2007-12-06 4:28 ` Hideo AOKI
2007-12-10 9:22 ` Herbert Xu
2007-12-11 1:28 ` Hideo AOKI
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=476362F6.1030700@redhat.com \
--to=haoki@redhat.com \
--cc=andi@firstfloor.org \
--cc=billfink@mindspring.com \
--cc=davem@davemloft.net \
--cc=herbert@gondor.apana.org.au \
--cc=johnpol@2ka.mipt.ru \
--cc=mhiramat@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=satoshi.oshima.fk@hitachi.com \
--cc=shemminger@linux-foundation.org \
--cc=tyasui@redhat.com \
--cc=yoshfuji@linux-ipv6.org \
--cc=yumiko.sugita.yf@hitachi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).