aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2010-05-20 04:43:18 -0400
committerJens Axboe <jens.axboe@oracle.com>2010-05-21 15:12:40 -0400
commit35f3d14dbbc58447c61e38a162ea10add6b31dc7 (patch)
tree3e03cd540b7dcdac82195c4e76862c0ce6daaaf0 /net/core
parent3d42b3612891baecf709d93f28655a6882a65d41 (diff)
pipe: add support for shrinking and growing pipes
This patch adds F_GETPIPE_SZ and F_SETPIPE_SZ fcntl() actions for growing and shrinking the size of a pipe and adjusts pipe.c and splice.c (and relay and network splice) usage to work with these larger (or smaller) pipes. Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/skbuff.c38
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 */
1420static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page, 1420static 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 */
1499static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, 1501static 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
1569done: 1575done:
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/**