aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZoltan Kiss <zoltan.kiss@citrix.com>2014-07-18 14:08:04 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-20 23:56:06 -0400
commit1b860da0404a76af8533099ffe0a965490939369 (patch)
treeefca7ccb372aa5ecf5774f06d3abe92af888dfce
parentb42cc6e421e7bf74e545483aa34b99d2a2ca6d3a (diff)
xen-netback: Fix releasing header slot on error path
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 PKT_PROT_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 <zoltan.kiss@citrix.com> Reported-by: Armin Zentai <armin.zentai@ezit.hu> Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: xen-devel@lists.xenproject.org Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/xen-netback/netback.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 8cbf60d4689e..6fff911dc134 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1039,6 +1039,8 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
1039 */ 1039 */
1040 struct skb_shared_info *first_shinfo = NULL; 1040 struct skb_shared_info *first_shinfo = NULL;
1041 int nr_frags = shinfo->nr_frags; 1041 int nr_frags = shinfo->nr_frags;
1042 const bool sharedslot = nr_frags &&
1043 frag_get_pending_idx(&shinfo->frags[0]) == pending_idx;
1042 int i, err; 1044 int i, err;
1043 1045
1044 /* Check status of header. */ 1046 /* Check status of header. */
@@ -1051,7 +1053,10 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
1051 (*gopp_copy)->status, 1053 (*gopp_copy)->status,
1052 pending_idx, 1054 pending_idx,
1053 (*gopp_copy)->source.u.ref); 1055 (*gopp_copy)->source.u.ref);
1054 xenvif_idx_release(queue, pending_idx, XEN_NETIF_RSP_ERROR); 1056 /* The first frag might still have this slot mapped */
1057 if (!sharedslot)
1058 xenvif_idx_release(queue, pending_idx,
1059 XEN_NETIF_RSP_ERROR);
1055 } 1060 }
1056 1061
1057check_frags: 1062check_frags:
@@ -1068,8 +1073,19 @@ check_frags:
1068 pending_idx, 1073 pending_idx,
1069 gop_map->handle); 1074 gop_map->handle);
1070 /* Had a previous error? Invalidate this fragment. */ 1075 /* Had a previous error? Invalidate this fragment. */
1071 if (unlikely(err)) 1076 if (unlikely(err)) {
1072 xenvif_idx_unmap(queue, pending_idx); 1077 xenvif_idx_unmap(queue, pending_idx);
1078 /* If the mapping of the first frag was OK, but
1079 * the header's copy failed, and they are
1080 * sharing a slot, send an error
1081 */
1082 if (i == 0 && sharedslot)
1083 xenvif_idx_release(queue, pending_idx,
1084 XEN_NETIF_RSP_ERROR);
1085 else
1086 xenvif_idx_release(queue, pending_idx,
1087 XEN_NETIF_RSP_OKAY);
1088 }
1073 continue; 1089 continue;
1074 } 1090 }
1075 1091
@@ -1081,15 +1097,27 @@ check_frags:
1081 gop_map->status, 1097 gop_map->status,
1082 pending_idx, 1098 pending_idx,
1083 gop_map->ref); 1099 gop_map->ref);
1100
1084 xenvif_idx_release(queue, pending_idx, XEN_NETIF_RSP_ERROR); 1101 xenvif_idx_release(queue, pending_idx, XEN_NETIF_RSP_ERROR);
1085 1102
1086 /* Not the first error? Preceding frags already invalidated. */ 1103 /* Not the first error? Preceding frags already invalidated. */
1087 if (err) 1104 if (err)
1088 continue; 1105 continue;
1089 /* First error: invalidate preceding fragments. */ 1106
1107 /* First error: if the header haven't shared a slot with the
1108 * first frag, release it as well.
1109 */
1110 if (!sharedslot)
1111 xenvif_idx_release(queue,
1112 XENVIF_TX_CB(skb)->pending_idx,
1113 XEN_NETIF_RSP_OKAY);
1114
1115 /* Invalidate preceding fragments of this skb. */
1090 for (j = 0; j < i; j++) { 1116 for (j = 0; j < i; j++) {
1091 pending_idx = frag_get_pending_idx(&shinfo->frags[j]); 1117 pending_idx = frag_get_pending_idx(&shinfo->frags[j]);
1092 xenvif_idx_unmap(queue, pending_idx); 1118 xenvif_idx_unmap(queue, pending_idx);
1119 xenvif_idx_release(queue, pending_idx,
1120 XEN_NETIF_RSP_OKAY);
1093 } 1121 }
1094 1122
1095 /* And if we found the error while checking the frag_list, unmap 1123 /* And if we found the error while checking the frag_list, unmap
@@ -1099,6 +1127,8 @@ check_frags:
1099 for (j = 0; j < first_shinfo->nr_frags; j++) { 1127 for (j = 0; j < first_shinfo->nr_frags; j++) {
1100 pending_idx = frag_get_pending_idx(&first_shinfo->frags[j]); 1128 pending_idx = frag_get_pending_idx(&first_shinfo->frags[j]);
1101 xenvif_idx_unmap(queue, pending_idx); 1129 xenvif_idx_unmap(queue, pending_idx);
1130 xenvif_idx_release(queue, pending_idx,
1131 XEN_NETIF_RSP_OKAY);
1102 } 1132 }
1103 } 1133 }
1104 1134
@@ -1834,8 +1864,6 @@ void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx)
1834 tx_unmap_op.status); 1864 tx_unmap_op.status);
1835 BUG(); 1865 BUG();
1836 } 1866 }
1837
1838 xenvif_idx_release(queue, pending_idx, XEN_NETIF_RSP_OKAY);
1839} 1867}
1840 1868
1841static inline int rx_work_todo(struct xenvif_queue *queue) 1869static inline int rx_work_todo(struct xenvif_queue *queue)