From patchwork Sun Dec 4 21:22:55 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: sjur.brandeland@stericsson.com X-Patchwork-Id: 129197 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 680771007D6 for ; Mon, 5 Dec 2011 08:23:44 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754173Ab1LDVXe (ORCPT ); Sun, 4 Dec 2011 16:23:34 -0500 Received: from mail-ee0-f46.google.com ([74.125.83.46]:64245 "EHLO mail-ee0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753262Ab1LDVXb (ORCPT ); Sun, 4 Dec 2011 16:23:31 -0500 Received: by mail-ee0-f46.google.com with SMTP id q14so1589448eea.19 for ; Sun, 04 Dec 2011 13:23:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:mime-version:content-type:content-transfer-encoding; bh=EoyEDz3gMmFn0gzsbtpItk51zknQ/g0Y3/FIae5ZTL8=; b=pS9ZZ6gtjpIwVUtbMnsSj4Uc6KRiG7h4ygudqXyECE8IQvwB8HScMPJw/kmv7t/tNk zIX1BhCP7I13cOTtqtj9WUPEynmc6Qop5FERMzbVwLJ6bsVsg26iPlcWtB9NAfp2l+9X ShhRLJmZ3AEMV2N7xVTko6pZeQj9IQRnzl4N0= Received: by 10.14.16.71 with SMTP id g47mr440694eeg.11.1323033810905; Sun, 04 Dec 2011 13:23:30 -0800 (PST) Received: from localhost.localdomain (125.80-203-142.nextgentel.com. [80.203.142.125]) by mx.google.com with ESMTPS id q28sm51604039eea.6.2011.12.04.13.23.29 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 04 Dec 2011 13:23:30 -0800 (PST) From: =?UTF-8?q?Sjur=20Br=C3=A6ndeland?= To: netdev@vger.kernel.org, David Miller Cc: Alexey Orishko , Eric Dumazet , =?UTF-8?q?Sjur=20Br=C3=A6ndeland?= Subject: [PATCHv3 net-next 4/4] caif: Stash away hijacked skb destructor and call it later Date: Sun, 4 Dec 2011 22:22:55 +0100 Message-Id: <1323033775-3496-4-git-send-email-sjur.brandeland@stericsson.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1323033775-3496-1-git-send-email-sjur.brandeland@stericsson.com> References: <1323033775-3496-1-git-send-email-sjur.brandeland@stericsson.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch adds functionality for avoiding orphaning SKB too early. The original skb is stashed away and the original destructor is called from the hi-jacked flow-on callback. If CAIF interface goes down and a hi-jacked SKB exists, the original skb->destructor is restored. Signed-off-by: Sjur Brændeland --- net/caif/caif_dev.c | 34 +++++++++++++++++++++++++++++++++- 1 files changed, 33 insertions(+), 1 deletions(-) diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index 74c1273..9b298c1 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -36,6 +36,8 @@ struct caif_device_entry { struct net_device *netdev; int __percpu *pcpu_refcnt; spinlock_t flow_lock; + struct sk_buff *xoff_skb; + void (*xoff_skb_dtor)(struct sk_buff *skb); bool xoff; }; @@ -133,6 +135,7 @@ static struct caif_device_entry *caif_get(struct net_device *dev) void caif_flow_cb(struct sk_buff *skb) { struct caif_device_entry *caifd; + void (*dtor)(struct sk_buff *skb) = NULL; bool send_xoff; WARN_ON(skb->dev == NULL); @@ -145,8 +148,17 @@ void caif_flow_cb(struct sk_buff *skb) spin_lock_bh(&caifd->flow_lock); send_xoff = caifd->xoff; caifd->xoff = 0; + if (!WARN_ON(caifd->xoff_skb_dtor == NULL)) { + WARN_ON(caifd->xoff_skb != skb); + dtor = caifd->xoff_skb_dtor; + caifd->xoff_skb = NULL; + caifd->xoff_skb_dtor = NULL; + } spin_unlock_bh(&caifd->flow_lock); + if (dtor) + dtor(skb); + if (send_xoff) caifd->layer.up-> ctrlcmd(caifd->layer.up, @@ -210,8 +222,10 @@ static int transmit(struct cflayer *layer, struct cfpkt *pkt) netif_queue_stopped(caifd->netdev), qlen, high); caifd->xoff = 1; + caifd->xoff_skb = skb; + caifd->xoff_skb_dtor = skb->destructor; + skb->destructor = caif_flow_cb; spin_unlock_bh(&caifd->flow_lock); - skb_orphan(skb); caifd->layer.up->ctrlcmd(caifd->layer.up, _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND, @@ -420,6 +434,24 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, caifd->layer.up->ctrlcmd(caifd->layer.up, _CAIF_CTRLCMD_PHYIF_DOWN_IND, caifd->layer.id); + + spin_lock_bh(&caifd->flow_lock); + + /* + * Replace our xoff-destructor with original destructor. + * We trust that skb->destructor *always* is called before + * the skb reference is invalid. The hijacked SKB destructor + * takes the flow_lock so manipulating the skb->destructor here + * should be safe. + */ + if (caifd->xoff_skb_dtor != NULL && caifd->xoff_skb != NULL) + caifd->xoff_skb->destructor = caifd->xoff_skb_dtor; + + caifd->xoff = 0; + caifd->xoff_skb_dtor = NULL; + caifd->xoff_skb = NULL; + + spin_unlock_bh(&caifd->flow_lock); caifd_put(caifd); break;