Commit f8c3bf00 authored by Paolo Abeni's avatar Paolo Abeni Committed by David S. Miller

net/socket: factor out helpers for memory and queue manipulation

Basic sock operations that udp code can use with its own
memory accounting schema. No functional change is introduced
in the existing APIs.

v4 -> v5:
  - avoid whitespace changes

v2 -> v4:
  - avoid exporting __sock_enqueue_skb

v1 -> v2:
  - avoid export sock_rmem_free
Acked-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Acked-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8b1efc0f
...@@ -1274,7 +1274,9 @@ static inline struct inode *SOCK_INODE(struct socket *socket) ...@@ -1274,7 +1274,9 @@ static inline struct inode *SOCK_INODE(struct socket *socket)
/* /*
* Functions for memory accounting * Functions for memory accounting
*/ */
int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind);
int __sk_mem_schedule(struct sock *sk, int size, int kind); int __sk_mem_schedule(struct sock *sk, int size, int kind);
void __sk_mem_reduce_allocated(struct sock *sk, int amount);
void __sk_mem_reclaim(struct sock *sk, int amount); void __sk_mem_reclaim(struct sock *sk, int amount);
#define SK_MEM_QUANTUM ((int)PAGE_SIZE) #define SK_MEM_QUANTUM ((int)PAGE_SIZE)
...@@ -1950,6 +1952,8 @@ void sk_reset_timer(struct sock *sk, struct timer_list *timer, ...@@ -1950,6 +1952,8 @@ void sk_reset_timer(struct sock *sk, struct timer_list *timer,
void sk_stop_timer(struct sock *sk, struct timer_list *timer); void sk_stop_timer(struct sock *sk, struct timer_list *timer);
int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
unsigned int flags);
int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
......
...@@ -323,6 +323,27 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len) ...@@ -323,6 +323,27 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len)
} }
EXPORT_SYMBOL(__skb_free_datagram_locked); EXPORT_SYMBOL(__skb_free_datagram_locked);
int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
unsigned int flags)
{
int err = 0;
if (flags & MSG_PEEK) {
err = -ENOENT;
spin_lock_bh(&sk->sk_receive_queue.lock);
if (skb == skb_peek(&sk->sk_receive_queue)) {
__skb_unlink(skb, &sk->sk_receive_queue);
atomic_dec(&skb->users);
err = 0;
}
spin_unlock_bh(&sk->sk_receive_queue.lock);
}
atomic_inc(&sk->sk_drops);
return err;
}
EXPORT_SYMBOL(__sk_queue_drop_skb);
/** /**
* skb_kill_datagram - Free a datagram skbuff forcibly * skb_kill_datagram - Free a datagram skbuff forcibly
* @sk: socket * @sk: socket
...@@ -346,23 +367,10 @@ EXPORT_SYMBOL(__skb_free_datagram_locked); ...@@ -346,23 +367,10 @@ EXPORT_SYMBOL(__skb_free_datagram_locked);
int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags) int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
{ {
int err = 0; int err = __sk_queue_drop_skb(sk, skb, flags);
if (flags & MSG_PEEK) {
err = -ENOENT;
spin_lock_bh(&sk->sk_receive_queue.lock);
if (skb == skb_peek(&sk->sk_receive_queue)) {
__skb_unlink(skb, &sk->sk_receive_queue);
atomic_dec(&skb->users);
err = 0;
}
spin_unlock_bh(&sk->sk_receive_queue.lock);
}
kfree_skb(skb); kfree_skb(skb);
atomic_inc(&sk->sk_drops);
sk_mem_reclaim_partial(sk); sk_mem_reclaim_partial(sk);
return err; return err;
} }
EXPORT_SYMBOL(skb_kill_datagram); EXPORT_SYMBOL(skb_kill_datagram);
......
...@@ -2091,24 +2091,18 @@ int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb) ...@@ -2091,24 +2091,18 @@ int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb)
EXPORT_SYMBOL(sk_wait_data); EXPORT_SYMBOL(sk_wait_data);
/** /**
* __sk_mem_schedule - increase sk_forward_alloc and memory_allocated * __sk_mem_raise_allocated - increase memory_allocated
* @sk: socket * @sk: socket
* @size: memory size to allocate * @size: memory size to allocate
* @amt: pages to allocate
* @kind: allocation type * @kind: allocation type
* *
* If kind is SK_MEM_SEND, it means wmem allocation. Otherwise it means * Similar to __sk_mem_schedule(), but does not update sk_forward_alloc
* rmem allocation. This function assumes that protocols which have
* memory_pressure use sk_wmem_queued as write buffer accounting.
*/ */
int __sk_mem_schedule(struct sock *sk, int size, int kind) int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind)
{ {
struct proto *prot = sk->sk_prot; struct proto *prot = sk->sk_prot;
int amt = sk_mem_pages(size); long allocated = sk_memory_allocated_add(sk, amt);
long allocated;
sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
allocated = sk_memory_allocated_add(sk, amt);
if (mem_cgroup_sockets_enabled && sk->sk_memcg && if (mem_cgroup_sockets_enabled && sk->sk_memcg &&
!mem_cgroup_charge_skmem(sk->sk_memcg, amt)) !mem_cgroup_charge_skmem(sk->sk_memcg, amt))
...@@ -2169,9 +2163,6 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind) ...@@ -2169,9 +2163,6 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind)
trace_sock_exceed_buf_limit(sk, prot, allocated); trace_sock_exceed_buf_limit(sk, prot, allocated);
/* Alas. Undo changes. */
sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM;
sk_memory_allocated_sub(sk, amt); sk_memory_allocated_sub(sk, amt);
if (mem_cgroup_sockets_enabled && sk->sk_memcg) if (mem_cgroup_sockets_enabled && sk->sk_memcg)
...@@ -2179,18 +2170,40 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind) ...@@ -2179,18 +2170,40 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind)
return 0; return 0;
} }
EXPORT_SYMBOL(__sk_mem_raise_allocated);
/**
* __sk_mem_schedule - increase sk_forward_alloc and memory_allocated
* @sk: socket
* @size: memory size to allocate
* @kind: allocation type
*
* If kind is SK_MEM_SEND, it means wmem allocation. Otherwise it means
* rmem allocation. This function assumes that protocols which have
* memory_pressure use sk_wmem_queued as write buffer accounting.
*/
int __sk_mem_schedule(struct sock *sk, int size, int kind)
{
int ret, amt = sk_mem_pages(size);
sk->sk_forward_alloc += amt << SK_MEM_QUANTUM_SHIFT;
ret = __sk_mem_raise_allocated(sk, size, amt, kind);
if (!ret)
sk->sk_forward_alloc -= amt << SK_MEM_QUANTUM_SHIFT;
return ret;
}
EXPORT_SYMBOL(__sk_mem_schedule); EXPORT_SYMBOL(__sk_mem_schedule);
/** /**
* __sk_mem_reclaim - reclaim memory_allocated * __sk_mem_reduce_allocated - reclaim memory_allocated
* @sk: socket * @sk: socket
* @amount: number of bytes (rounded down to a SK_MEM_QUANTUM multiple) * @amount: number of quanta
*
* Similar to __sk_mem_reclaim(), but does not update sk_forward_alloc
*/ */
void __sk_mem_reclaim(struct sock *sk, int amount) void __sk_mem_reduce_allocated(struct sock *sk, int amount)
{ {
amount >>= SK_MEM_QUANTUM_SHIFT;
sk_memory_allocated_sub(sk, amount); sk_memory_allocated_sub(sk, amount);
sk->sk_forward_alloc -= amount << SK_MEM_QUANTUM_SHIFT;
if (mem_cgroup_sockets_enabled && sk->sk_memcg) if (mem_cgroup_sockets_enabled && sk->sk_memcg)
mem_cgroup_uncharge_skmem(sk->sk_memcg, amount); mem_cgroup_uncharge_skmem(sk->sk_memcg, amount);
...@@ -2199,6 +2212,19 @@ void __sk_mem_reclaim(struct sock *sk, int amount) ...@@ -2199,6 +2212,19 @@ void __sk_mem_reclaim(struct sock *sk, int amount)
(sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0))) (sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0)))
sk_leave_memory_pressure(sk); sk_leave_memory_pressure(sk);
} }
EXPORT_SYMBOL(__sk_mem_reduce_allocated);
/**
* __sk_mem_reclaim - reclaim sk_forward_alloc and memory_allocated
* @sk: socket
* @amount: number of bytes (rounded down to a SK_MEM_QUANTUM multiple)
*/
void __sk_mem_reclaim(struct sock *sk, int amount)
{
amount >>= SK_MEM_QUANTUM_SHIFT;
sk->sk_forward_alloc -= amount << SK_MEM_QUANTUM_SHIFT;
__sk_mem_reduce_allocated(sk, amount);
}
EXPORT_SYMBOL(__sk_mem_reclaim); EXPORT_SYMBOL(__sk_mem_reclaim);
int sk_set_peek_off(struct sock *sk, int val) int sk_set_peek_off(struct sock *sk, int val)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment