Skip to content

Commit a10b91b

Browse files
committed
Merge branch 'udpmem'
Paolo Abeni says: ==================== udp: refactor memory accounting This patch series refactor the udp memory accounting, replacing the generic implementation with a custom one, in order to remove the needs for locking the socket on the enqueue and dequeue operations. The socket backlog usage is dropped, as well. The first patch factor out pieces of some queue and memory management socket helpers, so that they can later be used by the udp memory accounting functions. The second patch adds the memory account helpers, without using them. The third patch replacse the old rx memory accounting path for udp over ipv4 and udp over ipv6. In kernel UDP users are updated, as well. The memory accounting schema is described in detail in the individual patch commit message. The performance gain depends on the specific scenario; with few flows (and little contention in the original code) the differences are in the noise range, while with several flows contending the same socket, the measured speed-up is relevant (e.g. even over 100% in case of extreme contention) Many thanks to Eric Dumazet for the reiterated reviews and suggestions. v5 -> v6: - do not orphan the skb on enqueue, skb_steal_sock() already did the work for us v4 -> v5: - use the receive queue spin lock to protect the memory accounting - several minor clean-up v3 -> v4: - simplified the locking schema, always use a plain spinlock v2 -> v3: - do not set the now unsed backlog_rcv callback v1 -> v2: - changed slighly the memory accounting schema, we now perform lazy reclaim - fixed forward_alloc updating issue - fixed memory counter integer overflows ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 8b1efc0 + 850cbad commit a10b91b

File tree

8 files changed

+214
-99
lines changed

8 files changed

+214
-99
lines changed

include/net/sock.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,7 +1274,9 @@ static inline struct inode *SOCK_INODE(struct socket *socket)
12741274
/*
12751275
* Functions for memory accounting
12761276
*/
1277+
int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind);
12771278
int __sk_mem_schedule(struct sock *sk, int size, int kind);
1279+
void __sk_mem_reduce_allocated(struct sock *sk, int amount);
12781280
void __sk_mem_reclaim(struct sock *sk, int amount);
12791281

12801282
#define SK_MEM_QUANTUM ((int)PAGE_SIZE)
@@ -1950,6 +1952,8 @@ void sk_reset_timer(struct sock *sk, struct timer_list *timer,
19501952

19511953
void sk_stop_timer(struct sock *sk, struct timer_list *timer);
19521954

1955+
int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
1956+
unsigned int flags);
19531957
int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
19541958
int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
19551959

include/net/udp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,9 @@ static inline __be16 udp_flow_src_port(struct net *net, struct sk_buff *skb,
246246
}
247247

248248
/* net/ipv4/udp.c */
249+
void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len);
250+
int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb);
251+
249252
void udp_v4_early_demux(struct sk_buff *skb);
250253
int udp_get_port(struct sock *sk, unsigned short snum,
251254
int (*saddr_cmp)(const struct sock *,
@@ -258,6 +261,7 @@ void udp_flush_pending_frames(struct sock *sk);
258261
void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst);
259262
int udp_rcv(struct sk_buff *skb);
260263
int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
264+
int udp_init_sock(struct sock *sk);
261265
int udp_disconnect(struct sock *sk, int flags);
262266
unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait);
263267
struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,

net/core/datagram.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,27 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len)
323323
}
324324
EXPORT_SYMBOL(__skb_free_datagram_locked);
325325

326+
int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
327+
unsigned int flags)
328+
{
329+
int err = 0;
330+
331+
if (flags & MSG_PEEK) {
332+
err = -ENOENT;
333+
spin_lock_bh(&sk->sk_receive_queue.lock);
334+
if (skb == skb_peek(&sk->sk_receive_queue)) {
335+
__skb_unlink(skb, &sk->sk_receive_queue);
336+
atomic_dec(&skb->users);
337+
err = 0;
338+
}
339+
spin_unlock_bh(&sk->sk_receive_queue.lock);
340+
}
341+
342+
atomic_inc(&sk->sk_drops);
343+
return err;
344+
}
345+
EXPORT_SYMBOL(__sk_queue_drop_skb);
346+
326347
/**
327348
* skb_kill_datagram - Free a datagram skbuff forcibly
328349
* @sk: socket
@@ -346,23 +367,10 @@ EXPORT_SYMBOL(__skb_free_datagram_locked);
346367

347368
int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
348369
{
349-
int err = 0;
350-
351-
if (flags & MSG_PEEK) {
352-
err = -ENOENT;
353-
spin_lock_bh(&sk->sk_receive_queue.lock);
354-
if (skb == skb_peek(&sk->sk_receive_queue)) {
355-
__skb_unlink(skb, &sk->sk_receive_queue);
356-
atomic_dec(&skb->users);
357-
err = 0;
358-
}
359-
spin_unlock_bh(&sk->sk_receive_queue.lock);
360-
}
370+
int err = __sk_queue_drop_skb(sk, skb, flags);
361371

362372
kfree_skb(skb);
363-
atomic_inc(&sk->sk_drops);
364373
sk_mem_reclaim_partial(sk);
365-
366374
return err;
367375
}
368376
EXPORT_SYMBOL(skb_kill_datagram);

net/core/sock.c

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2091,24 +2091,18 @@ int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb)
20912091
EXPORT_SYMBOL(sk_wait_data);
20922092

20932093
/**
2094-
* __sk_mem_schedule - increase sk_forward_alloc and memory_allocated
2094+
* __sk_mem_raise_allocated - increase memory_allocated
20952095
* @sk: socket
20962096
* @size: memory size to allocate
2097+
* @amt: pages to allocate
20972098
* @kind: allocation type
20982099
*
2099-
* If kind is SK_MEM_SEND, it means wmem allocation. Otherwise it means
2100-
* rmem allocation. This function assumes that protocols which have
2101-
* memory_pressure use sk_wmem_queued as write buffer accounting.
2100+
* Similar to __sk_mem_schedule(), but does not update sk_forward_alloc
21022101
*/
2103-
int __sk_mem_schedule(struct sock *sk, int size, int kind)
2102+
int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind)
21042103
{
21052104
struct proto *prot = sk->sk_prot;
2106-
int amt = sk_mem_pages(size);
2107-
long allocated;
2108-
2109-
sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
2110-
2111-
allocated = sk_memory_allocated_add(sk, amt);
2105+
long allocated = sk_memory_allocated_add(sk, amt);
21122106

21132107
if (mem_cgroup_sockets_enabled && sk->sk_memcg &&
21142108
!mem_cgroup_charge_skmem(sk->sk_memcg, amt))
@@ -2169,28 +2163,47 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind)
21692163

21702164
trace_sock_exceed_buf_limit(sk, prot, allocated);
21712165

2172-
/* Alas. Undo changes. */
2173-
sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM;
2174-
21752166
sk_memory_allocated_sub(sk, amt);
21762167

21772168
if (mem_cgroup_sockets_enabled && sk->sk_memcg)
21782169
mem_cgroup_uncharge_skmem(sk->sk_memcg, amt);
21792170

21802171
return 0;
21812172
}
2173+
EXPORT_SYMBOL(__sk_mem_raise_allocated);
2174+
2175+
/**
2176+
* __sk_mem_schedule - increase sk_forward_alloc and memory_allocated
2177+
* @sk: socket
2178+
* @size: memory size to allocate
2179+
* @kind: allocation type
2180+
*
2181+
* If kind is SK_MEM_SEND, it means wmem allocation. Otherwise it means
2182+
* rmem allocation. This function assumes that protocols which have
2183+
* memory_pressure use sk_wmem_queued as write buffer accounting.
2184+
*/
2185+
int __sk_mem_schedule(struct sock *sk, int size, int kind)
2186+
{
2187+
int ret, amt = sk_mem_pages(size);
2188+
2189+
sk->sk_forward_alloc += amt << SK_MEM_QUANTUM_SHIFT;
2190+
ret = __sk_mem_raise_allocated(sk, size, amt, kind);
2191+
if (!ret)
2192+
sk->sk_forward_alloc -= amt << SK_MEM_QUANTUM_SHIFT;
2193+
return ret;
2194+
}
21822195
EXPORT_SYMBOL(__sk_mem_schedule);
21832196

21842197
/**
2185-
* __sk_mem_reclaim - reclaim memory_allocated
2198+
* __sk_mem_reduce_allocated - reclaim memory_allocated
21862199
* @sk: socket
2187-
* @amount: number of bytes (rounded down to a SK_MEM_QUANTUM multiple)
2200+
* @amount: number of quanta
2201+
*
2202+
* Similar to __sk_mem_reclaim(), but does not update sk_forward_alloc
21882203
*/
2189-
void __sk_mem_reclaim(struct sock *sk, int amount)
2204+
void __sk_mem_reduce_allocated(struct sock *sk, int amount)
21902205
{
2191-
amount >>= SK_MEM_QUANTUM_SHIFT;
21922206
sk_memory_allocated_sub(sk, amount);
2193-
sk->sk_forward_alloc -= amount << SK_MEM_QUANTUM_SHIFT;
21942207

21952208
if (mem_cgroup_sockets_enabled && sk->sk_memcg)
21962209
mem_cgroup_uncharge_skmem(sk->sk_memcg, amount);
@@ -2199,6 +2212,19 @@ void __sk_mem_reclaim(struct sock *sk, int amount)
21992212
(sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0)))
22002213
sk_leave_memory_pressure(sk);
22012214
}
2215+
EXPORT_SYMBOL(__sk_mem_reduce_allocated);
2216+
2217+
/**
2218+
* __sk_mem_reclaim - reclaim sk_forward_alloc and memory_allocated
2219+
* @sk: socket
2220+
* @amount: number of bytes (rounded down to a SK_MEM_QUANTUM multiple)
2221+
*/
2222+
void __sk_mem_reclaim(struct sock *sk, int amount)
2223+
{
2224+
amount >>= SK_MEM_QUANTUM_SHIFT;
2225+
sk->sk_forward_alloc -= amount << SK_MEM_QUANTUM_SHIFT;
2226+
__sk_mem_reduce_allocated(sk, amount);
2227+
}
22022228
EXPORT_SYMBOL(__sk_mem_reclaim);
22032229

22042230
int sk_set_peek_off(struct sock *sk, int val)

0 commit comments

Comments
 (0)