From patchwork Wed Oct 12 01:19:18 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Fleming X-Patchwork-Id: 119093 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 24E95B6F18 for ; Wed, 12 Oct 2011 12:22:02 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751580Ab1JLBV5 (ORCPT ); Tue, 11 Oct 2011 21:21:57 -0400 Received: from va3ehsobe010.messaging.microsoft.com ([216.32.180.30]:55826 "EHLO VA3EHSOBE010.bigfish.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751159Ab1JLBV4 (ORCPT ); Tue, 11 Oct 2011 21:21:56 -0400 Received: from mail103-va3-R.bigfish.com (10.7.14.244) by VA3EHSOBE010.bigfish.com (10.7.40.12) with Microsoft SMTP Server id 14.1.225.22; Wed, 12 Oct 2011 01:21:56 +0000 Received: from mail103-va3 (localhost.localdomain [127.0.0.1]) by mail103-va3-R.bigfish.com (Postfix) with ESMTP id 1EB049881DA; Wed, 12 Oct 2011 01:21:56 +0000 (UTC) X-SpamScore: 0 X-BigFish: VS0(zzzz1202hzz8275bhz2dh2a8h668h839h) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPVD:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-FB-SS: 0, Received: from mail103-va3 (localhost.localdomain [127.0.0.1]) by mail103-va3 (MessageSwitch) id 1318382452482492_19231; Wed, 12 Oct 2011 01:20:52 +0000 (UTC) Received: from VA3EHSMHS032.bigfish.com (unknown [10.7.14.253]) by mail103-va3.bigfish.com (Postfix) with ESMTP id 0BAC5140133; Wed, 12 Oct 2011 01:19:23 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by VA3EHSMHS032.bigfish.com (10.7.99.42) with Microsoft SMTP Server (TLS) id 14.1.225.22; Wed, 12 Oct 2011 01:19:20 +0000 Received: from az33smr01.freescale.net (10.64.34.199) by 039-SN1MMR1-003.039d.mgd.msft.net (10.84.1.16) with Microsoft SMTP Server id 14.1.339.2; Tue, 11 Oct 2011 20:19:19 -0500 Received: from localhost (right.am.freescale.net [10.82.193.13]) by az33smr01.freescale.net (8.13.1/8.13.0) with ESMTP id p9C1JILB011498; Tue, 11 Oct 2011 20:19:19 -0500 (CDT) From: Andy Fleming To: CC: Subject: [PATCH] net: Allow skb_recycle_check to be done in stages Date: Tue, 11 Oct 2011 20:19:18 -0500 Message-ID: <1318382358-2047-1-git-send-email-afleming@freescale.com> X-Mailer: git-send-email 1.7.3.4 MIME-Version: 1.0 X-OriginatorOrg: freescale.com Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org skb_recycle_check resets the skb if it's eligible for recycling. However, there are times when a driver might want to optionally manipulate the skb data with the skb before resetting the skb, but after it has determined eligibility. We do this by splitting the eligibility check from the skb reset, creating two inline functions to accomplish that task. Signed-off-by: Andy Fleming --- include/linux/skbuff.h | 21 +++++++++++++++++++ net/core/skbuff.c | 51 ++++++++++++++++++++++++----------------------- 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index ac6b05a..6b35ca1 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -525,6 +525,7 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size, return __alloc_skb(size, priority, 1, NUMA_NO_NODE); } +extern void skb_recycle(struct sk_buff *skb); extern bool skb_recycle_check(struct sk_buff *skb, int skb_size); extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); @@ -2459,5 +2460,25 @@ static inline void skb_checksum_none_assert(struct sk_buff *skb) bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off); +static inline bool skb_is_recycleable(struct sk_buff *skb, int skb_size) +{ + if (irqs_disabled()) + return false; + + if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) + return false; + + if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE) + return false; + + skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD); + if (skb_end_pointer(skb) - skb->head < skb_size) + return false; + + if (skb_shared(skb) || skb_cloned(skb)) + return false; + + return true; +} #endif /* __KERNEL__ */ #endif /* _LINUX_SKBUFF_H */ diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 5b2c5f1..48bee84 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -475,6 +475,30 @@ void consume_skb(struct sk_buff *skb) EXPORT_SYMBOL(consume_skb); /** + * skb_recycle - clean up an skb for reuse + * @skb: buffer + * + * Recycles the skb to be reused as a receive buffer. This + * function does any necessary reference count dropping, and + * cleans up the skbuff as if it just came from __alloc_skb(). + */ +void skb_recycle(struct sk_buff *skb) +{ + struct skb_shared_info *shinfo; + + skb_release_head_state(skb); + + shinfo = skb_shinfo(skb); + memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); + atomic_set(&shinfo->dataref, 1); + + memset(skb, 0, offsetof(struct sk_buff, tail)); + skb->data = skb->head + NET_SKB_PAD; + skb_reset_tail_pointer(skb); +} +EXPORT_SYMBOL(skb_recycle); + +/** * skb_recycle_check - check if skb can be reused for receive * @skb: buffer * @skb_size: minimum receive buffer size @@ -488,33 +512,10 @@ EXPORT_SYMBOL(consume_skb); */ bool skb_recycle_check(struct sk_buff *skb, int skb_size) { - struct skb_shared_info *shinfo; - - if (irqs_disabled()) - return false; - - if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) - return false; - - if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE) - return false; - - skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD); - if (skb_end_pointer(skb) - skb->head < skb_size) - return false; - - if (skb_shared(skb) || skb_cloned(skb)) + if (!skb_is_recycleable(skb, skb_size)) return false; - skb_release_head_state(skb); - - shinfo = skb_shinfo(skb); - memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); - atomic_set(&shinfo->dataref, 1); - - memset(skb, 0, offsetof(struct sk_buff, tail)); - skb->data = skb->head + NET_SKB_PAD; - skb_reset_tail_pointer(skb); + skb_recycle(skb); return true; }