Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754897AbaGQTMW (ORCPT ); Thu, 17 Jul 2014 15:12:22 -0400 Received: from smtp.citrix.com ([66.165.176.89]:55360 "EHLO SMTP.CITRIX.COM" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754260AbaGQTMU (ORCPT ); Thu, 17 Jul 2014 15:12:20 -0400 X-IronPort-AV: E=Sophos;i="5.01,679,1400025600"; d="scan'208";a="153463779" From: Zoltan Kiss To: Wei Liu , Ian Campbell CC: Zoltan Kiss , , , Subject: [PATCH for stable 3.15 3/4] xen-netback: Fix releasing header slot on error path Date: Thu, 17 Jul 2014 20:10:28 +0100 Message-ID: <1405624229-21817-3-git-send-email-zoltan.kiss@citrix.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1405624229-21817-1-git-send-email-zoltan.kiss@citrix.com> References: <1405624229-21817-1-git-send-email-zoltan.kiss@citrix.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.80.2.133] X-DLP: MIA2 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch makes this function aware that the first frag and the header might share the same ring slot. That could happen if the first slot is bigger than MAX_SKB_LEN. Due to this the error path might release that slot twice or never, depending on the error scenario. xenvif_idx_release is also removed from xenvif_idx_unmap, and called separately. Signed-off-by: Zoltan Kiss Reported-by: Armin Zentai Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: xen-devel@lists.xenproject.org diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 7b3e806..efc836e 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1016,6 +1016,8 @@ static int xenvif_tx_check_gop(struct xenvif *vif, */ struct skb_shared_info *first_shinfo = NULL; int nr_frags = shinfo->nr_frags; + const bool sharedslot = nr_frags && + frag_get_pending_idx(&shinfo->frags[0]) == pending_idx; int i, err; /* Check status of header. */ @@ -1028,7 +1030,10 @@ static int xenvif_tx_check_gop(struct xenvif *vif, (*gopp_copy)->status, pending_idx, (*gopp_copy)->source.u.ref); - xenvif_idx_release(vif, pending_idx, XEN_NETIF_RSP_ERROR); + /* The first frag might still have this slot mapped */ + if (!sharedslot) + xenvif_idx_release(vif, pending_idx, + XEN_NETIF_RSP_ERROR); } check_frags: @@ -1045,8 +1050,19 @@ check_frags: pending_idx, gop_map->handle); /* Had a previous error? Invalidate this fragment. */ - if (unlikely(err)) + if (unlikely(err)) { xenvif_idx_unmap(vif, pending_idx); + /* If the mapping of the first frag was OK, but + * the header's copy failed, and they are + * sharing a slot, send an error + */ + if (i == 0 && sharedslot) + xenvif_idx_release(vif, pending_idx, + XEN_NETIF_RSP_ERROR); + else + xenvif_idx_release(vif, pending_idx, + XEN_NETIF_RSP_OKAY); + } continue; } @@ -1058,15 +1074,26 @@ check_frags: gop_map->status, pending_idx, gop_map->ref); + xenvif_idx_release(vif, pending_idx, XEN_NETIF_RSP_ERROR); /* Not the first error? Preceding frags already invalidated. */ if (err) continue; - /* First error: invalidate preceding fragments. */ + + /* First error: if the header haven't shared a slot with the + * first frag, release it as well. + */ + if (!sharedslot) + xenvif_idx_release(vif, XENVIF_TX_CB(skb)->pending_idx, + XEN_NETIF_RSP_OKAY); + + /* Invalidate preceding fragments of this skb. */ for (j = 0; j < i; j++) { pending_idx = frag_get_pending_idx(&shinfo->frags[j]); xenvif_idx_unmap(vif, pending_idx); + xenvif_idx_release(vif, pending_idx, + XEN_NETIF_RSP_OKAY); } /* And if we found the error while checking the frag_list, unmap @@ -1076,6 +1103,8 @@ check_frags: for (j = 0; j < first_shinfo->nr_frags; j++) { pending_idx = frag_get_pending_idx(&first_shinfo->frags[j]); xenvif_idx_unmap(vif, pending_idx); + xenvif_idx_release(vif, pending_idx, + XEN_NETIF_RSP_OKAY); } } @@ -1807,8 +1836,6 @@ void xenvif_idx_unmap(struct xenvif *vif, u16 pending_idx) tx_unmap_op.status); BUG(); } - - xenvif_idx_release(vif, pending_idx, XEN_NETIF_RSP_OKAY); } static inline int rx_work_todo(struct xenvif *vif) -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/