diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 988fc49667b13ef16f8d059811bc90af78b1d149..37f539129d8964f92595bc3c2a06ca3eebda5ad7 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2566,5 +2566,19 @@ static inline bool skb_is_recycleable(const struct sk_buff *skb, int skb_size) return true; } + +/** + * skb_head_is_locked - Determine if the skb->head is locked down + * @skb: skb to check + * + * The head on skbs build around a head frag can be removed if they are + * not cloned. This function returns true if the skb head is locked down + * due to either being allocated via kmalloc, or by being a clone with + * multiple references to the head. + */ +static inline bool skb_head_is_locked(const struct sk_buff *skb) +{ + return !skb->head_frag || skb_cloned(skb); +} #endif /* __KERNEL__ */ #endif /* _LINUX_SKBUFF_H */ diff --git a/net/core/skbuff.c b/net/core/skbuff.c index e1f8bbaadf525e45cf601d8bc8cd94d2c7f90c8d..c199aa428c6dbfc7861876e8a171e470f11458bf 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1699,7 +1699,6 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe, struct splice_pipe_desc *spd, struct sock *sk) { int seg; - bool head_is_locked = !skb->head_frag || skb_cloned(skb); /* map the linear part : * If skb->head_frag is set, this 'linear' part is backed by a @@ -1710,7 +1709,7 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe, (unsigned long) skb->data & (PAGE_SIZE - 1), skb_headlen(skb), offset, len, skb, spd, - head_is_locked, + skb_head_is_locked(skb), sk, pipe)) return true; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 84e69e02fe20e7bee1ab83925882ac5c9ed437a1..7b2d351f24dbc2c5817bbcc5b20de146b275f3f9 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4568,7 +4568,7 @@ static bool tcp_try_coalesce(struct sock *sk, skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS) return false; - if (!from->head_frag || skb_cloned(from)) + if (skb_head_is_locked(from)) return false; delta = from->truesize - SKB_DATA_ALIGN(sizeof(struct sk_buff));