static void trim_sg(struct sock *sk, struct scatterlist *sg, int *sg_num_elem, unsigned int *sg_size, int target_size) { int i = *sg_num_elem - 1; int trim = *sg_size - target_size; if (trim <= 0) { WARN_ON(trim < 0); return; } *sg_size = target_size; while (trim >= sg[i].length) { trim -= sg[i].length; sk_mem_uncharge(sk, sg[i].length); put_page(sg_page(&sg[i])); i--; if (i < 0) goto out; } sg[i].length -= trim; sk_mem_uncharge(sk, trim); out: *sg_num_elem = i + 1; }
static void free_sg(struct sock *sk, struct scatterlist *sg, int *sg_num_elem, unsigned int *sg_size) { int i, n = *sg_num_elem; for (i = 0; i < n; ++i) { sk_mem_uncharge(sk, sg[i].length); put_page(sg_page(&sg[i])); } *sg_num_elem = 0; *sg_size = 0; }
static void kcm_rfree(struct sk_buff *skb) { struct sock *sk = skb->sk; struct kcm_sock *kcm = kcm_sk(sk); struct kcm_mux *mux = kcm->mux; unsigned int len = skb->truesize; sk_mem_uncharge(sk, len); atomic_sub(len, &sk->sk_rmem_alloc); /* For reading rx_wait and rx_psock without holding lock */ smp_mb__after_atomic(); if (!kcm->rx_wait && !kcm->rx_psock && sk_rmem_alloc_get(sk) < sk->sk_rcvlowat) { spin_lock_bh(&mux->rx_lock); kcm_rcv_ready(kcm); spin_unlock_bh(&mux->rx_lock); } }