Hello,
This patch set introduces new memory accounting interface.
Current interface is written for stream protocols only.
To enable memory accounting in other protocols (e.g. UDP),
I enhanced the interface and updated TCP and SCTP memory
accounting.
The patch set consists of the following 4 patches.
[1/4] introducing new memory accounting interface
[2/4] adding memory accounting points to consolidate functions
[3/4] updating TCP to use new interface
[4/4] updating SCTP to use new interface
The patch set was tested on net-2.6.25 tree.
Best regards,
Hideo Aoki
--
Hitachi Computer Products (America) Inc.
@@ -174,7 +174,8 @@ static inline void sctp_set_owner_w(strusizeof(structsctp_chunk);atomic_add(sizeof(structsctp_chunk),&sk->sk_wmem_alloc);-sk_charge_skb(sk,chunk->skb);+sk->sk_wmem_queued+=chunk->skb->truesize;+sk_mem_charge(sk,chunk->skb->truesize);}/* Verify that this is a valid address. */
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().
Cc: Satoshi Oshima <redacted>
Cc: Masami Hiramatsu <redacted>
signed-off-by: Takahiro Yasui <redacted>
signed-off-by: Hideo Aoki <redacted>
---
include/net/sock.h | 95 ++++++++++++++++++++++++++++++---------------------
net/core/sock.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
net/core/stream.c | 82 --------------------------------------------
3 files changed, 152 insertions(+), 122 deletions(-)
diff -pruN net-2.6.25/include/net/sock.h net-2.6.25-t12t19m-p1/include/net/sock.h
@@ -460,25 +460,6 @@ static inline int sk_stream_memory_free(returnsk->sk_wmem_queued<sk->sk_sndbuf;}-externvoidsk_stream_rfree(structsk_buff*skb);--staticinlinevoidsk_stream_set_owner_r(structsk_buff*skb,structsock*sk)-{-skb->sk=sk;-skb->destructor=sk_stream_rfree;-atomic_add(skb->truesize,&sk->sk_rmem_alloc);-sk->sk_forward_alloc-=skb->truesize;-}--staticinlinevoidsk_stream_free_skb(structsock*sk,structsk_buff*skb)-{-skb_truesize_check(skb);-sock_set_flag(sk,SOCK_QUEUE_SHRUNK);-sk->sk_wmem_queued-=skb->truesize;-sk->sk_forward_alloc+=skb->truesize;-__kfree_skb(skb);-}-/* The per-socket spinlock must be held here. */staticinlinevoidsk_add_backlog(structsock*sk,structsk_buff*skb){
@@ -576,7 +557,7 @@ struct proto {/**Pressureflag:trytocollapse.*Technicalnote:itisusedbymultiplecontextsnonatomically.-*Allthesk_stream_mem_schedule()isofthisnature:accounting+*Allthe__sk_mem_schedule()isofthisnature:accounting*isstrict,actionsareadvisoryandhavesomelatency.*/int*memory_pressure;
@@ -712,33 +693,73 @@ static inline struct inode *SOCK_INODE(sreturn&container_of(socket,structsocket_alloc,socket)->vfs_inode;}-externvoid__sk_stream_mem_reclaim(structsock*sk);-externintsk_stream_mem_schedule(structsock*sk,intsize,intkind);+/*+*Functionsformemoryaccounting+*/+externint__sk_mem_schedule(structsock*sk,intsize,intkind);+externvoid__sk_mem_reclaim(structsock*sk);-#define SK_STREAM_MEM_QUANTUM ((int)PAGE_SIZE)-#define SK_STREAM_MEM_QUANTUM_SHIFT ilog2(SK_STREAM_MEM_QUANTUM)+#define SK_MEM_QUANTUM ((int)PAGE_SIZE)+#define SK_MEM_QUANTUM_SHIFT ilog2(SK_MEM_QUANTUM)+#define SK_MEM_SEND 0+#define SK_MEM_RECV 1-staticinlineintsk_stream_pages(intamt)+staticinlineintsk_mem_pages(intamt){-return(amt+SK_STREAM_MEM_QUANTUM-1)>>SK_STREAM_MEM_QUANTUM_SHIFT;+return(amt+SK_MEM_QUANTUM-1)>>SK_MEM_QUANTUM_SHIFT;}-staticinlinevoidsk_stream_mem_reclaim(structsock*sk)+staticinlineintsk_has_account(structsock*sk){-if(sk->sk_forward_alloc>=SK_STREAM_MEM_QUANTUM)-__sk_stream_mem_reclaim(sk);+/* return true if protocol supports memory accounting */+return!!sk->sk_prot->memory_allocated;}-staticinlineintsk_stream_rmem_schedule(structsock*sk,structsk_buff*skb)+staticinlineintsk_wmem_schedule(structsock*sk,intsize){-return(int)skb->truesize<=sk->sk_forward_alloc||-sk_stream_mem_schedule(sk,skb->truesize,1);+if(!sk_has_account(sk))+return1;+returnsize<=sk->sk_forward_alloc||+__sk_mem_schedule(sk,size,SK_MEM_SEND);}-staticinlineintsk_stream_wmem_schedule(structsock*sk,intsize)+staticinlineintsk_rmem_schedule(structsock*sk,intsize){+if(!sk_has_account(sk))+return1;returnsize<=sk->sk_forward_alloc||-sk_stream_mem_schedule(sk,size,0);+__sk_mem_schedule(sk,size,SK_MEM_RECV);+}++staticinlinevoidsk_mem_reclaim(structsock*sk)+{+if(!sk_has_account(sk))+return;+if(sk->sk_forward_alloc>=SK_MEM_QUANTUM)+__sk_mem_reclaim(sk);+}++staticinlinevoidsk_mem_charge(structsock*sk,intsize)+{+if(!sk_has_account(sk))+return;+sk->sk_forward_alloc-=size;+}++staticinlinevoidsk_mem_uncharge(structsock*sk,intsize)+{+if(!sk_has_account(sk))+return;+sk->sk_forward_alloc+=size;+}++staticinlinevoidsk_wmem_free_skb(structsock*sk,structsk_buff*skb)+{+skb_truesize_check(skb);+sock_set_flag(sk,SOCK_QUEUE_SHRUNK);+sk->sk_wmem_queued-=skb->truesize;+sk_mem_uncharge(sk,skb->truesize);+__kfree_skb(skb);}/* Used by processes to "lock" a socket state, so that
@@ -1076,12 +1097,6 @@ static inline int sk_can_gso(const strucexternvoidsk_setup_caps(structsock*sk,structdst_entry*dst);-staticinlinevoidsk_charge_skb(structsock*sk,structsk_buff*skb)-{-sk->sk_wmem_queued+=skb->truesize;-sk->sk_forward_alloc-=skb->truesize;-}-staticinlineintskb_copy_to_page(structsock*sk,char__user*from,structsk_buff*skb,structpage*page,intoff,intcopy)
@@ -1384,6 +1384,103 @@ int sk_wait_data(struct sock *sk, long *EXPORT_SYMBOL(sk_wait_data);+/**+*__sk_mem_schedule-increasesk_forward_allocandmemory_allocated+*@sk:socket+*@size:memorysizetoallocate+*@kind:allocationtype+*+*IfkindisSK_MEM_SEND,itmeanswmemallocation.Otherwiseitmeans+*rmemallocation.Thisfunctionassumesthatprotocolswhichhave+*memory_pressureusesk_wmem_queuedaswritebufferaccounting.+*/+int__sk_mem_schedule(structsock*sk,intsize,intkind)+{+structproto*prot=sk->sk_prot;+intamt=sk_mem_pages(size);+intallocated;++sk->sk_forward_alloc+=amt*SK_MEM_QUANTUM;+allocated=atomic_add_return(amt,prot->memory_allocated);++/* Under limit. */+if(allocated<=prot->sysctl_mem[0]){+if(prot->memory_pressure&&*prot->memory_pressure)+*prot->memory_pressure=0;+return1;+}++/* Under pressure. */+if(allocated>prot->sysctl_mem[1])+if(prot->enter_memory_pressure)+prot->enter_memory_pressure();++/* Over hard limit. */+if(allocated>prot->sysctl_mem[2])+gotosuppress_allocation;++/* guarantee minimum buffer size under pressure */+if(kind==SK_MEM_RECV){+if(atomic_read(&sk->sk_rmem_alloc)<prot->sysctl_rmem[0])+return1;+}else{/* SK_MEM_SEND */+if(sk->sk_type==SOCK_STREAM){+if(sk->sk_wmem_queued<prot->sysctl_wmem[0])+return1;+}elseif(atomic_read(&sk->sk_wmem_alloc)<+prot->sysctl_wmem[0])+return1;+}++if(prot->memory_pressure){+if(!*prot->memory_pressure||+prot->sysctl_mem[2]>atomic_read(prot->sockets_allocated)*+sk_mem_pages(sk->sk_wmem_queued++atomic_read(&sk->sk_rmem_alloc)++sk->sk_forward_alloc))+return1;+}++suppress_allocation:++if(kind==SK_MEM_SEND&&sk->sk_type==SOCK_STREAM){+sk_stream_moderate_sndbuf(sk);++/* Fail only if socket is _under_ its sndbuf.+*Inthiscasewecannotblock,sothatwehavetofail.+*/+if(sk->sk_wmem_queued+size>=sk->sk_sndbuf)+return1;+}++/* Alas. Undo changes. */+sk->sk_forward_alloc-=amt*SK_MEM_QUANTUM;+atomic_sub(amt,prot->memory_allocated);+return0;+}++EXPORT_SYMBOL(__sk_mem_schedule);++/**+*__sk_reclaim-reclaimmemory_allocated+*@sk:socket+*/+void__sk_mem_reclaim(structsock*sk)+{+structproto*prot=sk->sk_prot;++atomic_sub(sk->sk_forward_alloc/SK_MEM_QUANTUM,+prot->memory_allocated);+sk->sk_forward_alloc&=SK_MEM_QUANTUM-1;++if(prot->memory_pressure&&*prot->memory_pressure&&+(atomic_read(prot->memory_allocated)<prot->sysctl_mem[0]))+*prot->memory_pressure=0;+}++EXPORT_SYMBOL(__sk_mem_reclaim);++/**Setofdefaultroutinesforinitialisingstructproto_opswhen*theprotocoldoesnotsupportaparticularfunction.Incertain
@@ -194,77 +183,6 @@ int sk_stream_error(struct sock *sk, intEXPORT_SYMBOL(sk_stream_error);-void__sk_stream_mem_reclaim(structsock*sk)-{-atomic_sub(sk->sk_forward_alloc>>SK_STREAM_MEM_QUANTUM_SHIFT,-sk->sk_prot->memory_allocated);-sk->sk_forward_alloc&=SK_STREAM_MEM_QUANTUM-1;-if(*sk->sk_prot->memory_pressure&&-(atomic_read(sk->sk_prot->memory_allocated)<-sk->sk_prot->sysctl_mem[0]))-*sk->sk_prot->memory_pressure=0;-}--EXPORT_SYMBOL(__sk_stream_mem_reclaim);--intsk_stream_mem_schedule(structsock*sk,intsize,intkind)-{-intamt=sk_stream_pages(size);-structproto*prot=sk->sk_prot;--sk->sk_forward_alloc+=amt*SK_STREAM_MEM_QUANTUM;-atomic_add(amt,prot->memory_allocated);--/* Under limit. */-if(atomic_read(prot->memory_allocated)<prot->sysctl_mem[0]){-if(*prot->memory_pressure)-*prot->memory_pressure=0;-return1;-}--/* Over hard limit. */-if(atomic_read(prot->memory_allocated)>prot->sysctl_mem[2]){-prot->enter_memory_pressure();-gotosuppress_allocation;-}--/* Under pressure. */-if(atomic_read(prot->memory_allocated)>prot->sysctl_mem[1])-prot->enter_memory_pressure();--if(kind){-if(atomic_read(&sk->sk_rmem_alloc)<prot->sysctl_rmem[0])-return1;-}elseif(sk->sk_wmem_queued<prot->sysctl_wmem[0])-return1;--if(!*prot->memory_pressure||-prot->sysctl_mem[2]>atomic_read(prot->sockets_allocated)*-sk_stream_pages(sk->sk_wmem_queued+-atomic_read(&sk->sk_rmem_alloc)+-sk->sk_forward_alloc))-return1;--suppress_allocation:--if(!kind){-sk_stream_moderate_sndbuf(sk);--/* Fail only if socket is _under_ its sndbuf.-*Inthiscasewecannotblock,sothatwehavetofail.-*/-if(sk->sk_wmem_queued+size>=sk->sk_sndbuf)-return1;-}--/* Alas. Undo changes. */-sk->sk_forward_alloc-=amt*SK_STREAM_MEM_QUANTUM;-atomic_sub(amt,prot->memory_allocated);-return0;-}--EXPORT_SYMBOL(sk_stream_mem_schedule);-voidsk_stream_kill_queues(structsock*sk){/* First the read buffer. */
@@ -1738,7 +1739,7 @@ void tcp_close(struct sock *sk, long tim__kfree_skb(skb);}-sk_stream_mem_reclaim(sk);+sk_mem_reclaim(sk);/* As outlined in RFC 2525, section 2.17, we send a RST here because*datawaslost.Towitnesstheawfuleffectsoftheoldbehaviorof
@@ -3934,7 +3934,7 @@ drop:SOCK_DEBUG(sk,"out of order segment: rcv_next %X seq %X - %X\n",tp->rcv_nxt,TCP_SKB_CB(skb)->seq,TCP_SKB_CB(skb)->end_seq);-sk_stream_set_owner_r(skb,sk);+skb_set_owner_r(skb,sk);if(!skb_peek(&tp->out_of_order_queue)){/* Initial out of order segment, build 1 SACK. */
@@ -701,7 +702,8 @@ int tcp_fragment(struct sock *sk, structif(buff==NULL)return-ENOMEM;/* We'll just try again later. */-sk_charge_skb(sk,buff);+sk->sk_wmem_queued+=buff->truesize;+sk_mem_charge(sk,buff->truesize);nlen=skb->len-len-nsize;buff->truesize+=nlen;skb->truesize-=nlen;
@@ -825,7 +827,7 @@ int tcp_trim_head(struct sock *sk, strucskb->truesize-=len;sk->sk_wmem_queued-=len;-sk->sk_forward_alloc+=len;+sk_mem_uncharge(sk,len);sock_set_flag(sk,SOCK_QUEUE_SHRUNK);/* Any change of skb->len requires recalculation of tso
@@ -1197,7 +1199,8 @@ static int tso_fragment(struct sock *sk,if(unlikely(buff==NULL))return-ENOMEM;-sk_charge_skb(sk,buff);+sk->sk_wmem_queued+=buff->truesize;+sk_mem_charge(sk,buff->truesize);buff->truesize+=nlen;skb->truesize-=nlen;
@@ -1350,7 +1353,8 @@ static int tcp_mtu_probe(struct sock *sk/* We're allowed to probe. Build it now. */if((nskb=sk_stream_alloc_skb(sk,probe_size,GFP_ATOMIC))==NULL)return-1;-sk_charge_skb(sk,nskb);+sk->sk_wmem_queued+=nskb->truesize;+sk_mem_charge(sk,nskb->truesize);skb=tcp_send_head(sk);
@@ -1377,7 +1381,7 @@ static int tcp_mtu_probe(struct sock *sk*Throwitaway.*/TCP_SKB_CB(nskb)->flags|=TCP_SKB_CB(skb)->flags;tcp_unlink_write_queue(skb,sk);-sk_stream_free_skb(sk,skb);+sk_wmem_free_skb(sk,skb);}else{TCP_SKB_CB(nskb)->flags|=TCP_SKB_CB(skb)->flags&~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
@@ -1744,7 +1748,7 @@ static void tcp_retrans_try_collapse(str/* changed transmit queue under us so clear hints */tcp_clear_retrans_hints_partial(tp);-sk_stream_free_skb(sk,next_skb);+sk_wmem_free_skb(sk,next_skb);}}
@@ -2139,8 +2143,9 @@ int tcp_send_synack(struct sock *sk)tcp_unlink_write_queue(skb,sk);skb_header_release(nskb);__tcp_add_write_queue_head(sk,nskb);-sk_stream_free_skb(sk,skb);-sk_charge_skb(sk,nskb);+sk_wmem_free_skb(sk,skb);+sk->sk_wmem_queued+=nskb->truesize;+sk_mem_charge(sk,nskb->truesize);skb=nskb;}
@@ -2343,7 +2348,8 @@ int tcp_connect(struct sock *sk)tp->retrans_stamp=TCP_SKB_CB(buff)->when;skb_header_release(buff);__tcp_add_write_queue_tail(sk,buff);-sk_charge_skb(sk,buff);+sk->sk_wmem_queued+=buff->truesize;+sk_mem_charge(sk,buff->truesize);tp->packets_out+=tcp_skb_pcount(buff);tcp_transmit_skb(sk,buff,1,GFP_KERNEL);
Hello,
This patch set introduces new memory accounting interface.
Current interface is written for stream protocols only.
To enable memory accounting in other protocols (e.g. UDP),
I enhanced the interface and updated TCP and SCTP memory
accounting.
The patch set consists of the following 4 patches.
[1/4] introducing new memory accounting interface
[2/4] adding memory accounting points to consolidate functions
[3/4] updating TCP to use new interface
[4/4] updating SCTP to use new interface
The patch set was tested on net-2.6.25 tree.
I like this work very much and will add this to net-2.6.25
But I will have to combine it all into one patch.
You cannot have one patch which breaks the build in any way. All of
the kernel must build properly after each patch in your patchset is
applied.
Since patch 1 renames all of the sk_stream_*() functions, TCP and SCTP
stop building.
We enforce this rule, otherwise when users try to use "git bisect" to
find out where regressions are added, they will get stuck in places
like this where the tree will not build due to such careless
changesets.
Thank you.
And now I see exactly what you did, and it is quite careless.
You wrote one big patch then tried to split it up by hand. This
proves to me that you did not test the patches individually. Even
worse, you did not even try to apply each patch nor compile the tree
each step along the way as a basic sanity check.
This wastes a lot of my time, as well as the time of other developers
who might want to try out and test your changes.
I will fix it up this time, but please do not ever do this again.
Hello,
This patch set introduces new memory accounting interface.
Current interface is written for stream protocols only.
To enable memory accounting in other protocols (e.g. UDP),
I enhanced the interface and updated TCP and SCTP memory
accounting.
The patch set consists of the following 4 patches.
[1/4] introducing new memory accounting interface
[2/4] adding memory accounting points to consolidate functions
[3/4] updating TCP to use new interface
[4/4] updating SCTP to use new interface
The patch set was tested on net-2.6.25 tree.
I like this work very much and will add this to net-2.6.25
But I will have to combine it all into one patch.
You cannot have one patch which breaks the build in any way. All of
the kernel must build properly after each patch in your patchset is
applied.
Since patch 1 renames all of the sk_stream_*() functions, TCP and SCTP
stop building.
We enforce this rule, otherwise when users try to use "git bisect" to
find out where regressions are added, they will get stuck in places
like this where the tree will not build due to such careless
changesets.
Hi David
Could you add the following patch, because it apparently was lost
during the battle :)
Thank you
[PATCH] use SK_MEM_QUANTUM_SHIFT in __sk_mem_reclaim()
Avoid an expensive divide (as done in commit
18030477e70a826b91608aee40a987bbd368fec6 but lost in commit
23821d2653111d20e75472c8c5003df1a55309a8)
Signed-off-by: Eric Dumazet <redacted>
The patch set consists of the following 4 patches.
[1/4] introducing new memory accounting interface
[2/4] adding memory accounting points to consolidate functions
[3/4] updating TCP to use new interface
[4/4] updating SCTP to use new interface
I like this work very much and will add this to net-2.6.25
But I will have to combine it all into one patch.
You cannot have one patch which breaks the build in any way. All of
the kernel must build properly after each patch in your patchset is
applied.
Since patch 1 renames all of the sk_stream_*() functions, TCP and SCTP
stop building.
That's correct.
We enforce this rule, otherwise when users try to use "git bisect" to
find out where regressions are added, they will get stuck in places
like this where the tree will not build due to such careless
changesets.
Thank you for your explanation. To be honest, I didn't know the rule
exactly. I am so sorry for sending inconvenient patch set.
Best regards,
Hideo
--
Hitachi Computer Products (America) Inc.
This patch would not apply, because is contained changes
present in the first patch, specifically:
<snip>
And now I see exactly what you did, and it is quite careless.
You wrote one big patch then tried to split it up by hand. This
proves to me that you did not test the patches individually. Even
worse, you did not even try to apply each patch nor compile the tree
each step along the way as a basic sanity check.
Hello David,
You are right. Since I felt the patch was big, I divided
into three for review. And I mistook during the dividing.
This wastes a lot of my time, as well as the time of other developers
who might want to try out and test your changes.
I apologize for wasting your time.
I will fix it up this time, but please do not ever do this again.
I really appreciate the fix. And I understood this.
Best regards,
Hideo
--
Hitachi Computer Products (America) Inc.
Hi David
Could you add the following patch, because it apparently was lost
during the battle :)
Thank you
[PATCH] use SK_MEM_QUANTUM_SHIFT in __sk_mem_reclaim()
Avoid an expensive divide (as done in commit
18030477e70a826b91608aee40a987bbd368fec6 but lost in commit
23821d2653111d20e75472c8c5003df1a55309a8)
Hello Eric,
Thank you for catching this. I'm sorry about the lost.
Best regards,
Hideo
--
Hitachi Computer Products (America) Inc.
From: David Miller <davem@davemloft.net> Date: 2007-12-31 23:01:30
From: Eric Dumazet <redacted>
Date: Mon, 31 Dec 2007 16:17:37 +0100
Could you add the following patch, because it apparently was lost
during the battle :)
Thank you
[PATCH] use SK_MEM_QUANTUM_SHIFT in __sk_mem_reclaim()
Avoid an expensive divide (as done in commit
18030477e70a826b91608aee40a987bbd368fec6 but lost in commit
23821d2653111d20e75472c8c5003df1a55309a8)
Signed-off-by: Eric Dumazet <redacted>
Sigh :-/
Thanks for catching this Eric, patch applied.