aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@citrix.com>2013-09-11 09:52:48 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-10-13 19:08:29 -0400
commit0ff773f59ff375c42af2238457bda98ed4ddcd25 (patch)
tree32e1a514a9fdb0912ecfb81280f804fd6a3c346f
parent872b11be53a4594c39262433c4176176fcb12bd2 (diff)
xen-netback: count number required slots for an skb more carefully
[ Upstream commit 6e43fc04a6bc357d260583b8440882f28069207f ] When a VM is providing an iSCSI target and the LUN is used by the backend domain, the generated skbs for direct I/O writes to the disk have large, multi-page skb->data but no frags. With some lengths and starting offsets, xen_netbk_count_skb_slots() would be one short because the simple calculation of DIV_ROUND_UP(skb_headlen(), PAGE_SIZE) was not accounting for the decisions made by start_new_rx_buffer() which does not guarantee responses are fully packed. For example, a skb with length < 2 pages but which spans 3 pages would be counted as requiring 2 slots but would actually use 3 slots. skb->data: | 1111|222222222222|3333 | Fully packed, this would need 2 slots: |111122222222|22223333 | But because the 2nd page wholy fits into a slot it is not split across slots and goes into a slot of its own: |1111 |222222222222|3333 | Miscounting the number of slots means netback may push more responses than the number of available requests. This will cause the frontend to get very confused and report "Too many frags/slots". The frontend never recovers and will eventually BUG. Fix this by counting the number of required slots more carefully. In xen_netbk_count_skb_slots(), more closely follow the algorithm used by xen_netbk_gop_skb() by introducing xen_netbk_count_frag_slots() which is the dry-run equivalent of netbk_gop_frag_copy(). Signed-off-by: David Vrabel <david.vrabel@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/xen-netback/netback.c94
1 files changed, 64 insertions, 30 deletions
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 8c20935d72c9..0071f211a08a 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -354,6 +354,49 @@ static bool start_new_rx_buffer(int offset, unsigned long size, int head)
354 return false; 354 return false;
355} 355}
356 356
357struct xenvif_count_slot_state {
358 unsigned long copy_off;
359 bool head;
360};
361
362unsigned int xenvif_count_frag_slots(struct xenvif *vif,
363 unsigned long offset, unsigned long size,
364 struct xenvif_count_slot_state *state)
365{
366 unsigned count = 0;
367
368 offset &= ~PAGE_MASK;
369
370 while (size > 0) {
371 unsigned long bytes;
372
373 bytes = PAGE_SIZE - offset;
374
375 if (bytes > size)
376 bytes = size;
377
378 if (start_new_rx_buffer(state->copy_off, bytes, state->head)) {
379 count++;
380 state->copy_off = 0;
381 }
382
383 if (state->copy_off + bytes > MAX_BUFFER_OFFSET)
384 bytes = MAX_BUFFER_OFFSET - state->copy_off;
385
386 state->copy_off += bytes;
387
388 offset += bytes;
389 size -= bytes;
390
391 if (offset == PAGE_SIZE)
392 offset = 0;
393
394 state->head = false;
395 }
396
397 return count;
398}
399
357/* 400/*
358 * Figure out how many ring slots we're going to need to send @skb to 401 * Figure out how many ring slots we're going to need to send @skb to
359 * the guest. This function is essentially a dry run of 402 * the guest. This function is essentially a dry run of
@@ -361,48 +404,39 @@ static bool start_new_rx_buffer(int offset, unsigned long size, int head)
361 */ 404 */
362unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb) 405unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb)
363{ 406{
407 struct xenvif_count_slot_state state;
364 unsigned int count; 408 unsigned int count;
365 int i, copy_off; 409 unsigned char *data;
410 unsigned i;
366 411
367 count = DIV_ROUND_UP(skb_headlen(skb), PAGE_SIZE); 412 state.head = true;
413 state.copy_off = 0;
368 414
369 copy_off = skb_headlen(skb) % PAGE_SIZE; 415 /* Slot for the first (partial) page of data. */
416 count = 1;
370 417
418 /* Need a slot for the GSO prefix for GSO extra data? */
371 if (skb_shinfo(skb)->gso_size) 419 if (skb_shinfo(skb)->gso_size)
372 count++; 420 count++;
373 421
374 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 422 data = skb->data;
375 unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]); 423 while (data < skb_tail_pointer(skb)) {
376 unsigned long offset = skb_shinfo(skb)->frags[i].page_offset; 424 unsigned long offset = offset_in_page(data);
377 unsigned long bytes; 425 unsigned long size = PAGE_SIZE - offset;
378
379 offset &= ~PAGE_MASK;
380
381 while (size > 0) {
382 BUG_ON(offset >= PAGE_SIZE);
383 BUG_ON(copy_off > MAX_BUFFER_OFFSET);
384
385 bytes = PAGE_SIZE - offset;
386
387 if (bytes > size)
388 bytes = size;
389 426
390 if (start_new_rx_buffer(copy_off, bytes, 0)) { 427 if (data + size > skb_tail_pointer(skb))
391 count++; 428 size = skb_tail_pointer(skb) - data;
392 copy_off = 0;
393 }
394 429
395 if (copy_off + bytes > MAX_BUFFER_OFFSET) 430 count += xenvif_count_frag_slots(vif, offset, size, &state);
396 bytes = MAX_BUFFER_OFFSET - copy_off;
397 431
398 copy_off += bytes; 432 data += size;
433 }
399 434
400 offset += bytes; 435 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
401 size -= bytes; 436 unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
437 unsigned long offset = skb_shinfo(skb)->frags[i].page_offset;
402 438
403 if (offset == PAGE_SIZE) 439 count += xenvif_count_frag_slots(vif, offset, size, &state);
404 offset = 0;
405 }
406 } 440 }
407 return count; 441 return count;
408} 442}