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

mptcp: drop tx skb cache

The mentioned cache was introduced to reduce the number of skb
allocation in atomic context, but the required complexity is
excessive.

This change remove the mentioned cache.
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarMat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 070258ef
...@@ -902,22 +902,14 @@ static bool mptcp_frag_can_collapse_to(const struct mptcp_sock *msk, ...@@ -902,22 +902,14 @@ static bool mptcp_frag_can_collapse_to(const struct mptcp_sock *msk,
df->data_seq + df->data_len == msk->write_seq; df->data_seq + df->data_len == msk->write_seq;
} }
static int mptcp_wmem_with_overhead(struct sock *sk, int size) static int mptcp_wmem_with_overhead(int size)
{ {
struct mptcp_sock *msk = mptcp_sk(sk); return size + ((sizeof(struct mptcp_data_frag) * size) >> PAGE_SHIFT);
int ret, skbs;
ret = size + ((sizeof(struct mptcp_data_frag) * size) >> PAGE_SHIFT);
skbs = (msk->tx_pending_data + size) / msk->size_goal_cache;
if (skbs < msk->skb_tx_cache.qlen)
return ret;
return ret + (skbs - msk->skb_tx_cache.qlen) * SKB_TRUESIZE(MAX_TCP_HEADER);
} }
static void __mptcp_wmem_reserve(struct sock *sk, int size) static void __mptcp_wmem_reserve(struct sock *sk, int size)
{ {
int amount = mptcp_wmem_with_overhead(sk, size); int amount = mptcp_wmem_with_overhead(size);
struct mptcp_sock *msk = mptcp_sk(sk); struct mptcp_sock *msk = mptcp_sk(sk);
WARN_ON_ONCE(msk->wmem_reserved); WARN_ON_ONCE(msk->wmem_reserved);
...@@ -1212,49 +1204,8 @@ static struct sk_buff *__mptcp_do_alloc_tx_skb(struct sock *sk, gfp_t gfp) ...@@ -1212,49 +1204,8 @@ static struct sk_buff *__mptcp_do_alloc_tx_skb(struct sock *sk, gfp_t gfp)
return NULL; return NULL;
} }
static bool mptcp_tx_cache_refill(struct sock *sk, int size,
struct sk_buff_head *skbs, int *total_ts)
{
struct mptcp_sock *msk = mptcp_sk(sk);
struct sk_buff *skb;
int space_needed;
if (unlikely(tcp_under_memory_pressure(sk))) {
mptcp_mem_reclaim_partial(sk);
/* under pressure pre-allocate at most a single skb */
if (msk->skb_tx_cache.qlen)
return true;
space_needed = msk->size_goal_cache;
} else {
space_needed = msk->tx_pending_data + size -
msk->skb_tx_cache.qlen * msk->size_goal_cache;
}
while (space_needed > 0) {
skb = __mptcp_do_alloc_tx_skb(sk, sk->sk_allocation);
if (unlikely(!skb)) {
/* under memory pressure, try to pass the caller a
* single skb to allow forward progress
*/
while (skbs->qlen > 1) {
skb = __skb_dequeue_tail(skbs);
*total_ts -= skb->truesize;
__kfree_skb(skb);
}
return skbs->qlen > 0;
}
*total_ts += skb->truesize;
__skb_queue_tail(skbs, skb);
space_needed -= msk->size_goal_cache;
}
return true;
}
static bool __mptcp_alloc_tx_skb(struct sock *sk, struct sock *ssk, gfp_t gfp) static bool __mptcp_alloc_tx_skb(struct sock *sk, struct sock *ssk, gfp_t gfp)
{ {
struct mptcp_sock *msk = mptcp_sk(sk);
struct sk_buff *skb; struct sk_buff *skb;
if (ssk->sk_tx_skb_cache) { if (ssk->sk_tx_skb_cache) {
...@@ -1265,22 +1216,6 @@ static bool __mptcp_alloc_tx_skb(struct sock *sk, struct sock *ssk, gfp_t gfp) ...@@ -1265,22 +1216,6 @@ static bool __mptcp_alloc_tx_skb(struct sock *sk, struct sock *ssk, gfp_t gfp)
return true; return true;
} }
skb = skb_peek(&msk->skb_tx_cache);
if (skb) {
if (likely(sk_wmem_schedule(ssk, skb->truesize))) {
skb = __skb_dequeue(&msk->skb_tx_cache);
if (WARN_ON_ONCE(!skb))
return false;
mptcp_wmem_uncharge(sk, skb->truesize);
ssk->sk_tx_skb_cache = skb;
return true;
}
/* over memory limit, no point to try to allocate a new skb */
return false;
}
skb = __mptcp_do_alloc_tx_skb(sk, gfp); skb = __mptcp_do_alloc_tx_skb(sk, gfp);
if (!skb) if (!skb)
return false; return false;
...@@ -1296,7 +1231,6 @@ static bool __mptcp_alloc_tx_skb(struct sock *sk, struct sock *ssk, gfp_t gfp) ...@@ -1296,7 +1231,6 @@ static bool __mptcp_alloc_tx_skb(struct sock *sk, struct sock *ssk, gfp_t gfp)
static bool mptcp_must_reclaim_memory(struct sock *sk, struct sock *ssk) static bool mptcp_must_reclaim_memory(struct sock *sk, struct sock *ssk)
{ {
return !ssk->sk_tx_skb_cache && return !ssk->sk_tx_skb_cache &&
!skb_peek(&mptcp_sk(sk)->skb_tx_cache) &&
tcp_under_memory_pressure(sk); tcp_under_memory_pressure(sk);
} }
...@@ -1339,7 +1273,6 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk, ...@@ -1339,7 +1273,6 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
/* compute send limit */ /* compute send limit */
info->mss_now = tcp_send_mss(ssk, &info->size_goal, info->flags); info->mss_now = tcp_send_mss(ssk, &info->size_goal, info->flags);
avail_size = info->size_goal; avail_size = info->size_goal;
msk->size_goal_cache = info->size_goal;
skb = tcp_write_queue_tail(ssk); skb = tcp_write_queue_tail(ssk);
if (skb) { if (skb) {
/* Limit the write to the size available in the /* Limit the write to the size available in the
...@@ -1688,7 +1621,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) ...@@ -1688,7 +1621,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
while (msg_data_left(msg)) { while (msg_data_left(msg)) {
int total_ts, frag_truesize = 0; int total_ts, frag_truesize = 0;
struct mptcp_data_frag *dfrag; struct mptcp_data_frag *dfrag;
struct sk_buff_head skbs;
bool dfrag_collapsed; bool dfrag_collapsed;
size_t psize, offset; size_t psize, offset;
...@@ -1721,16 +1653,10 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) ...@@ -1721,16 +1653,10 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
psize = pfrag->size - offset; psize = pfrag->size - offset;
psize = min_t(size_t, psize, msg_data_left(msg)); psize = min_t(size_t, psize, msg_data_left(msg));
total_ts = psize + frag_truesize; total_ts = psize + frag_truesize;
__skb_queue_head_init(&skbs);
if (!mptcp_tx_cache_refill(sk, psize, &skbs, &total_ts))
goto wait_for_memory;
if (!mptcp_wmem_alloc(sk, total_ts)) { if (!mptcp_wmem_alloc(sk, total_ts))
__skb_queue_purge(&skbs);
goto wait_for_memory; goto wait_for_memory;
}
skb_queue_splice_tail(&skbs, &msk->skb_tx_cache);
if (copy_page_from_iter(dfrag->page, offset, psize, if (copy_page_from_iter(dfrag->page, offset, psize,
&msg->msg_iter) != psize) { &msg->msg_iter) != psize) {
mptcp_wmem_uncharge(sk, psize + frag_truesize); mptcp_wmem_uncharge(sk, psize + frag_truesize);
...@@ -2462,13 +2388,11 @@ static int __mptcp_init_sock(struct sock *sk) ...@@ -2462,13 +2388,11 @@ static int __mptcp_init_sock(struct sock *sk)
INIT_LIST_HEAD(&msk->rtx_queue); INIT_LIST_HEAD(&msk->rtx_queue);
INIT_WORK(&msk->work, mptcp_worker); INIT_WORK(&msk->work, mptcp_worker);
__skb_queue_head_init(&msk->receive_queue); __skb_queue_head_init(&msk->receive_queue);
__skb_queue_head_init(&msk->skb_tx_cache);
msk->out_of_order_queue = RB_ROOT; msk->out_of_order_queue = RB_ROOT;
msk->first_pending = NULL; msk->first_pending = NULL;
msk->wmem_reserved = 0; msk->wmem_reserved = 0;
msk->rmem_released = 0; msk->rmem_released = 0;
msk->tx_pending_data = 0; msk->tx_pending_data = 0;
msk->size_goal_cache = TCP_BASE_MSS;
msk->ack_hint = NULL; msk->ack_hint = NULL;
msk->first = NULL; msk->first = NULL;
...@@ -2525,15 +2449,10 @@ static void __mptcp_clear_xmit(struct sock *sk) ...@@ -2525,15 +2449,10 @@ static void __mptcp_clear_xmit(struct sock *sk)
{ {
struct mptcp_sock *msk = mptcp_sk(sk); struct mptcp_sock *msk = mptcp_sk(sk);
struct mptcp_data_frag *dtmp, *dfrag; struct mptcp_data_frag *dtmp, *dfrag;
struct sk_buff *skb;
WRITE_ONCE(msk->first_pending, NULL); WRITE_ONCE(msk->first_pending, NULL);
list_for_each_entry_safe(dfrag, dtmp, &msk->rtx_queue, list) list_for_each_entry_safe(dfrag, dtmp, &msk->rtx_queue, list)
dfrag_clear(sk, dfrag); dfrag_clear(sk, dfrag);
while ((skb = __skb_dequeue(&msk->skb_tx_cache)) != NULL) {
sk->sk_forward_alloc += skb->truesize;
kfree_skb(skb);
}
} }
static void mptcp_cancel_work(struct sock *sk) static void mptcp_cancel_work(struct sock *sk)
......
...@@ -245,9 +245,7 @@ struct mptcp_sock { ...@@ -245,9 +245,7 @@ struct mptcp_sock {
struct sk_buff *ooo_last_skb; struct sk_buff *ooo_last_skb;
struct rb_root out_of_order_queue; struct rb_root out_of_order_queue;
struct sk_buff_head receive_queue; struct sk_buff_head receive_queue;
struct sk_buff_head skb_tx_cache; /* this is wmem accounted */
int tx_pending_data; int tx_pending_data;
int size_goal_cache;
struct list_head conn_list; struct list_head conn_list;
struct list_head rtx_queue; struct list_head rtx_queue;
struct mptcp_data_frag *first_pending; struct mptcp_data_frag *first_pending;
......
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