diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/skbuff.c | 38 |
1 files changed, 21 insertions, 17 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 93c4e060c91e..931981774b1a 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -1417,12 +1417,13 @@ new_page: | |||
1417 | /* | 1417 | /* |
1418 | * Fill page/offset/length into spd, if it can hold more pages. | 1418 | * Fill page/offset/length into spd, if it can hold more pages. |
1419 | */ | 1419 | */ |
1420 | static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page, | 1420 | static inline int spd_fill_page(struct splice_pipe_desc *spd, |
1421 | struct pipe_inode_info *pipe, struct page *page, | ||
1421 | unsigned int *len, unsigned int offset, | 1422 | unsigned int *len, unsigned int offset, |
1422 | struct sk_buff *skb, int linear, | 1423 | struct sk_buff *skb, int linear, |
1423 | struct sock *sk) | 1424 | struct sock *sk) |
1424 | { | 1425 | { |
1425 | if (unlikely(spd->nr_pages == PIPE_BUFFERS)) | 1426 | if (unlikely(spd->nr_pages == pipe->buffers)) |
1426 | return 1; | 1427 | return 1; |
1427 | 1428 | ||
1428 | if (linear) { | 1429 | if (linear) { |
@@ -1458,7 +1459,8 @@ static inline int __splice_segment(struct page *page, unsigned int poff, | |||
1458 | unsigned int plen, unsigned int *off, | 1459 | unsigned int plen, unsigned int *off, |
1459 | unsigned int *len, struct sk_buff *skb, | 1460 | unsigned int *len, struct sk_buff *skb, |
1460 | struct splice_pipe_desc *spd, int linear, | 1461 | struct splice_pipe_desc *spd, int linear, |
1461 | struct sock *sk) | 1462 | struct sock *sk, |
1463 | struct pipe_inode_info *pipe) | ||
1462 | { | 1464 | { |
1463 | if (!*len) | 1465 | if (!*len) |
1464 | return 1; | 1466 | return 1; |
@@ -1481,7 +1483,7 @@ static inline int __splice_segment(struct page *page, unsigned int poff, | |||
1481 | /* the linear region may spread across several pages */ | 1483 | /* the linear region may spread across several pages */ |
1482 | flen = min_t(unsigned int, flen, PAGE_SIZE - poff); | 1484 | flen = min_t(unsigned int, flen, PAGE_SIZE - poff); |
1483 | 1485 | ||
1484 | if (spd_fill_page(spd, page, &flen, poff, skb, linear, sk)) | 1486 | if (spd_fill_page(spd, pipe, page, &flen, poff, skb, linear, sk)) |
1485 | return 1; | 1487 | return 1; |
1486 | 1488 | ||
1487 | __segment_seek(&page, &poff, &plen, flen); | 1489 | __segment_seek(&page, &poff, &plen, flen); |
@@ -1496,9 +1498,9 @@ static inline int __splice_segment(struct page *page, unsigned int poff, | |||
1496 | * Map linear and fragment data from the skb to spd. It reports failure if the | 1498 | * Map linear and fragment data from the skb to spd. It reports failure if the |
1497 | * pipe is full or if we already spliced the requested length. | 1499 | * pipe is full or if we already spliced the requested length. |
1498 | */ | 1500 | */ |
1499 | static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, | 1501 | static int __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe, |
1500 | unsigned int *len, struct splice_pipe_desc *spd, | 1502 | unsigned int *offset, unsigned int *len, |
1501 | struct sock *sk) | 1503 | struct splice_pipe_desc *spd, struct sock *sk) |
1502 | { | 1504 | { |
1503 | int seg; | 1505 | int seg; |
1504 | 1506 | ||
@@ -1508,7 +1510,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, | |||
1508 | if (__splice_segment(virt_to_page(skb->data), | 1510 | if (__splice_segment(virt_to_page(skb->data), |
1509 | (unsigned long) skb->data & (PAGE_SIZE - 1), | 1511 | (unsigned long) skb->data & (PAGE_SIZE - 1), |
1510 | skb_headlen(skb), | 1512 | skb_headlen(skb), |
1511 | offset, len, skb, spd, 1, sk)) | 1513 | offset, len, skb, spd, 1, sk, pipe)) |
1512 | return 1; | 1514 | return 1; |
1513 | 1515 | ||
1514 | /* | 1516 | /* |
@@ -1518,7 +1520,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, | |||
1518 | const skb_frag_t *f = &skb_shinfo(skb)->frags[seg]; | 1520 | const skb_frag_t *f = &skb_shinfo(skb)->frags[seg]; |
1519 | 1521 | ||
1520 | if (__splice_segment(f->page, f->page_offset, f->size, | 1522 | if (__splice_segment(f->page, f->page_offset, f->size, |
1521 | offset, len, skb, spd, 0, sk)) | 1523 | offset, len, skb, spd, 0, sk, pipe)) |
1522 | return 1; | 1524 | return 1; |
1523 | } | 1525 | } |
1524 | 1526 | ||
@@ -1535,8 +1537,8 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, | |||
1535 | struct pipe_inode_info *pipe, unsigned int tlen, | 1537 | struct pipe_inode_info *pipe, unsigned int tlen, |
1536 | unsigned int flags) | 1538 | unsigned int flags) |
1537 | { | 1539 | { |
1538 | struct partial_page partial[PIPE_BUFFERS]; | 1540 | struct partial_page partial[PIPE_DEF_BUFFERS]; |
1539 | struct page *pages[PIPE_BUFFERS]; | 1541 | struct page *pages[PIPE_DEF_BUFFERS]; |
1540 | struct splice_pipe_desc spd = { | 1542 | struct splice_pipe_desc spd = { |
1541 | .pages = pages, | 1543 | .pages = pages, |
1542 | .partial = partial, | 1544 | .partial = partial, |
@@ -1546,12 +1548,16 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, | |||
1546 | }; | 1548 | }; |
1547 | struct sk_buff *frag_iter; | 1549 | struct sk_buff *frag_iter; |
1548 | struct sock *sk = skb->sk; | 1550 | struct sock *sk = skb->sk; |
1551 | int ret = 0; | ||
1552 | |||
1553 | if (splice_grow_spd(pipe, &spd)) | ||
1554 | return -ENOMEM; | ||
1549 | 1555 | ||
1550 | /* | 1556 | /* |
1551 | * __skb_splice_bits() only fails if the output has no room left, | 1557 | * __skb_splice_bits() only fails if the output has no room left, |
1552 | * so no point in going over the frag_list for the error case. | 1558 | * so no point in going over the frag_list for the error case. |
1553 | */ | 1559 | */ |
1554 | if (__skb_splice_bits(skb, &offset, &tlen, &spd, sk)) | 1560 | if (__skb_splice_bits(skb, pipe, &offset, &tlen, &spd, sk)) |
1555 | goto done; | 1561 | goto done; |
1556 | else if (!tlen) | 1562 | else if (!tlen) |
1557 | goto done; | 1563 | goto done; |
@@ -1562,14 +1568,12 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, | |||
1562 | skb_walk_frags(skb, frag_iter) { | 1568 | skb_walk_frags(skb, frag_iter) { |
1563 | if (!tlen) | 1569 | if (!tlen) |
1564 | break; | 1570 | break; |
1565 | if (__skb_splice_bits(frag_iter, &offset, &tlen, &spd, sk)) | 1571 | if (__skb_splice_bits(frag_iter, pipe, &offset, &tlen, &spd, sk)) |
1566 | break; | 1572 | break; |
1567 | } | 1573 | } |
1568 | 1574 | ||
1569 | done: | 1575 | done: |
1570 | if (spd.nr_pages) { | 1576 | if (spd.nr_pages) { |
1571 | int ret; | ||
1572 | |||
1573 | /* | 1577 | /* |
1574 | * Drop the socket lock, otherwise we have reverse | 1578 | * Drop the socket lock, otherwise we have reverse |
1575 | * locking dependencies between sk_lock and i_mutex | 1579 | * locking dependencies between sk_lock and i_mutex |
@@ -1582,10 +1586,10 @@ done: | |||
1582 | release_sock(sk); | 1586 | release_sock(sk); |
1583 | ret = splice_to_pipe(pipe, &spd); | 1587 | ret = splice_to_pipe(pipe, &spd); |
1584 | lock_sock(sk); | 1588 | lock_sock(sk); |
1585 | return ret; | ||
1586 | } | 1589 | } |
1587 | 1590 | ||
1588 | return 0; | 1591 | splice_shrink_spd(pipe, &spd); |
1592 | return ret; | ||
1589 | } | 1593 | } |
1590 | 1594 | ||
1591 | /** | 1595 | /** |