From patchwork Tue Nov 30 00:40:29 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Changli Gao X-Patchwork-Id: 73512 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 193D5B6EF1 for ; Tue, 30 Nov 2010 11:40:59 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755306Ab0K3Aky (ORCPT ); Mon, 29 Nov 2010 19:40:54 -0500 Received: from mail-pz0-f46.google.com ([209.85.210.46]:54818 "EHLO mail-pz0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754776Ab0K3Akx (ORCPT ); Mon, 29 Nov 2010 19:40:53 -0500 Received: by pzk6 with SMTP id 6so794032pzk.19 for ; Mon, 29 Nov 2010 16:40:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:subject:date :message-id:x-mailer; bh=+woJdWVMzxQTu3qCBNgn24H96FQNa557Y5oDF+6IwOc=; b=kofzeK6tz9BkCv+ZD7InOjhx7+H/p9qvO2dyZLnNq8CE0oR8msSU6AtC8G0Bh/rzeW WkGlYRsDFxWgt1+GmfmS90oJRpvFu9oHLhL+8RmyrMRyQxfzXirXb6Yt8Dr9v2TuJN9p xhI5Vzj8VlurGGRVU3MUnht0WU30OMEJ1NEIg= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; b=K3yG6mRSQtATBrKz6oyssDz2Cap+bbTXugW90QoLU2S01+/kbsScNE3qcfr91nj5kw NRlJ/M/ihmE8cXZW8qlvDoAnCw1tXTpkOyt76GjbPDaWQBru16Mk3MHN4WepkpRX4ugp NeQRF/imFZTJ3icyl6PrC2DztxdzYel+JySkQ= Received: by 10.142.89.20 with SMTP id m20mr6348231wfb.13.1291077653224; Mon, 29 Nov 2010 16:40:53 -0800 (PST) Received: from localhost.localdomain ([221.239.34.230]) by mx.google.com with ESMTPS id w42sm8186643wfh.15.2010.11.29.16.40.44 (version=TLSv1/SSLv3 cipher=RC4-MD5); Mon, 29 Nov 2010 16:40:51 -0800 (PST) From: Changli Gao To: "David S. Miller" Cc: netdev@vger.kernel.org, Changli Gao Subject: [PATCH v2] net: avoid the unnecessary kmalloc Date: Tue, 30 Nov 2010 08:40:29 +0800 Message-Id: <1291077629-6339-1-git-send-email-xiaosuo@gmail.com> X-Mailer: git-send-email 1.7.1 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org If the old memory allocated by kmalloc() is larger than the new requested, pskb_expand_head() doesn't need to allocate a new one, unless the skb->head is shared. Signed-off-by: Changli Gao --- v2: apply this trick for the cloned but not shared skb net/core/skbuff.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 104f844..8814a9a 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -778,6 +778,28 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, size = SKB_DATA_ALIGN(size); + /* Check if we can avoid taking references on fragments if we own + * the last reference on skb->head. (see skb_release_data()) + */ + if (!skb->cloned) + fastpath = true; + else { + int delta = skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1; + + fastpath = atomic_read(&skb_shinfo(skb)->dataref) == delta; + } + + if (fastpath && + size + sizeof(struct skb_shared_info) <= ksize(skb->head)) { + memmove(skb->head + size, skb_shinfo(skb), + offsetof(struct skb_shared_info, + frags[skb_shinfo(skb)->nr_frags])); + memmove(skb->head + nhead, skb->head, + skb_tail_pointer(skb) - skb->head); + off = nhead; + goto adjust_others; + } + data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask); if (!data) goto nodata; @@ -791,17 +813,6 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, skb_shinfo(skb), offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags])); - /* Check if we can avoid taking references on fragments if we own - * the last reference on skb->head. (see skb_release_data()) - */ - if (!skb->cloned) - fastpath = true; - else { - int delta = skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1; - - fastpath = atomic_read(&skb_shinfo(skb)->dataref) == delta; - } - if (fastpath) { kfree(skb->head); } else { @@ -816,6 +827,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, off = (data + nhead) - skb->head; skb->head = data; +adjust_others: skb->data += off; #ifdef NET_SKBUFF_DATA_USES_OFFSET skb->end = size;