diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-06-16 04:52:13 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-16 11:55:39 -0700 |
commit | 317fe0e6c5dc9448bcef41a2e31fecfd3dba7f55 (patch) | |
tree | c2a042e1c8bb96b7fdeadf658309ead1b6e8dabc /include | |
parent | fdb93f8ac39aa5902f3d264edd50dffcabfdd13b (diff) |
inetpeer: restore small inet_peer structures
Addition of rcu_head to struct inet_peer added 16bytes on 64bit arches.
Thats a bit unfortunate, since old size was exactly 64 bytes.
This can be solved, using an union between this rcu_head an four fields,
that are normally used only when a refcount is taken on inet_peer.
rcu_head is used only when refcnt=-1, right before structure freeing.
Add a inet_peer_refcheck() function to check this assertion for a while.
We can bring back SLAB_HWCACHE_ALIGN qualifier in kmem cache creation.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r-- | include/net/inetpeer.h | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index 61740473042..417d0c894f2 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h @@ -22,11 +22,21 @@ struct inet_peer { __u32 dtime; /* the time of last use of not * referenced entries */ atomic_t refcnt; - atomic_t rid; /* Frag reception counter */ - atomic_t ip_id_count; /* IP ID for the next packet */ - __u32 tcp_ts; - __u32 tcp_ts_stamp; - struct rcu_head rcu; + /* + * Once inet_peer is queued for deletion (refcnt == -1), following fields + * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp + * We can share memory with rcu_head to keep inet_peer small + * (less then 64 bytes) + */ + union { + struct { + atomic_t rid; /* Frag reception counter */ + atomic_t ip_id_count; /* IP ID for the next packet */ + __u32 tcp_ts; + __u32 tcp_ts_stamp; + }; + struct rcu_head rcu; + }; }; void inet_initpeers(void) __init; @@ -37,10 +47,21 @@ struct inet_peer *inet_getpeer(__be32 daddr, int create); /* can be called from BH context or outside */ extern void inet_putpeer(struct inet_peer *p); +/* + * temporary check to make sure we dont access rid, ip_id_count, tcp_ts, + * tcp_ts_stamp if no refcount is taken on inet_peer + */ +static inline void inet_peer_refcheck(const struct inet_peer *p) +{ + WARN_ON_ONCE(atomic_read(&p->refcnt) <= 0); +} + + /* can be called with or without local BH being disabled */ static inline __u16 inet_getid(struct inet_peer *p, int more) { more++; + inet_peer_refcheck(p); return atomic_add_return(more, &p->ip_id_count) - more; } |