projects
/
linux-2.6-block.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
pipe: add support for shrinking and growing pipes
[linux-2.6-block.git]
/
net
/
core
/
skbuff.c
diff --git
a/net/core/skbuff.c
b/net/core/skbuff.c
index 93c4e060c91e7bffb121d51eeccd264337214491..931981774b1a56a3eed61c6219e84c67192abad7 100644
(file)
--- a/
net/core/skbuff.c
+++ b/
net/core/skbuff.c
@@
-1417,12
+1417,13
@@
new_page:
/*
* Fill page/offset/length into spd, if it can hold more pages.
*/
/*
* Fill page/offset/length into spd, if it can hold more pages.
*/
-static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page,
+static inline int spd_fill_page(struct splice_pipe_desc *spd,
+ struct pipe_inode_info *pipe, struct page *page,
unsigned int *len, unsigned int offset,
struct sk_buff *skb, int linear,
struct sock *sk)
{
unsigned int *len, unsigned int offset,
struct sk_buff *skb, int linear,
struct sock *sk)
{
- if (unlikely(spd->nr_pages ==
PIPE_BUFFERS
))
+ if (unlikely(spd->nr_pages ==
pipe->buffers
))
return 1;
if (linear) {
return 1;
if (linear) {
@@
-1458,7
+1459,8
@@
static inline int __splice_segment(struct page *page, unsigned int poff,
unsigned int plen, unsigned int *off,
unsigned int *len, struct sk_buff *skb,
struct splice_pipe_desc *spd, int linear,
unsigned int plen, unsigned int *off,
unsigned int *len, struct sk_buff *skb,
struct splice_pipe_desc *spd, int linear,
- struct sock *sk)
+ struct sock *sk,
+ struct pipe_inode_info *pipe)
{
if (!*len)
return 1;
{
if (!*len)
return 1;
@@
-1481,7
+1483,7
@@
static inline int __splice_segment(struct page *page, unsigned int poff,
/* the linear region may spread across several pages */
flen = min_t(unsigned int, flen, PAGE_SIZE - poff);
/* the linear region may spread across several pages */
flen = min_t(unsigned int, flen, PAGE_SIZE - poff);
- if (spd_fill_page(spd, page, &flen, poff, skb, linear, sk))
+ if (spd_fill_page(spd, p
ipe, p
age, &flen, poff, skb, linear, sk))
return 1;
__segment_seek(&page, &poff, &plen, flen);
return 1;
__segment_seek(&page, &poff, &plen, flen);
@@
-1496,9
+1498,9
@@
static inline int __splice_segment(struct page *page, unsigned int poff,
* Map linear and fragment data from the skb to spd. It reports failure if the
* pipe is full or if we already spliced the requested length.
*/
* Map linear and fragment data from the skb to spd. It reports failure if the
* pipe is full or if we already spliced the requested length.
*/
-static int __skb_splice_bits(struct sk_buff *skb,
unsigned int *offset
,
- unsigned int *
len, struct splice_pipe_desc *spd
,
- struct sock *sk)
+static int __skb_splice_bits(struct sk_buff *skb,
struct pipe_inode_info *pipe
,
+ unsigned int *
offset, unsigned int *len
,
+ struct s
plice_pipe_desc *spd, struct s
ock *sk)
{
int seg;
{
int seg;
@@
-1508,7
+1510,7
@@
static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,
if (__splice_segment(virt_to_page(skb->data),
(unsigned long) skb->data & (PAGE_SIZE - 1),
skb_headlen(skb),
if (__splice_segment(virt_to_page(skb->data),
(unsigned long) skb->data & (PAGE_SIZE - 1),
skb_headlen(skb),
- offset, len, skb, spd, 1, sk))
+ offset, len, skb, spd, 1, sk
, pipe
))
return 1;
/*
return 1;
/*
@@
-1518,7
+1520,7
@@
static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,
const skb_frag_t *f = &skb_shinfo(skb)->frags[seg];
if (__splice_segment(f->page, f->page_offset, f->size,
const skb_frag_t *f = &skb_shinfo(skb)->frags[seg];
if (__splice_segment(f->page, f->page_offset, f->size,
- offset, len, skb, spd, 0, sk))
+ offset, len, skb, spd, 0, sk
, pipe
))
return 1;
}
return 1;
}
@@
-1535,8
+1537,8
@@
int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
struct pipe_inode_info *pipe, unsigned int tlen,
unsigned int flags)
{
struct pipe_inode_info *pipe, unsigned int tlen,
unsigned int flags)
{
- struct partial_page partial[PIPE_BUFFERS];
- struct page *pages[PIPE_BUFFERS];
+ struct partial_page partial[PIPE_
DEF_
BUFFERS];
+ struct page *pages[PIPE_
DEF_
BUFFERS];
struct splice_pipe_desc spd = {
.pages = pages,
.partial = partial,
struct splice_pipe_desc spd = {
.pages = pages,
.partial = partial,
@@
-1546,12
+1548,16
@@
int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
};
struct sk_buff *frag_iter;
struct sock *sk = skb->sk;
};
struct sk_buff *frag_iter;
struct sock *sk = skb->sk;
+ int ret = 0;
+
+ if (splice_grow_spd(pipe, &spd))
+ return -ENOMEM;
/*
* __skb_splice_bits() only fails if the output has no room left,
* so no point in going over the frag_list for the error case.
*/
/*
* __skb_splice_bits() only fails if the output has no room left,
* so no point in going over the frag_list for the error case.
*/
- if (__skb_splice_bits(skb, &offset, &tlen, &spd, sk))
+ if (__skb_splice_bits(skb,
pipe,
&offset, &tlen, &spd, sk))
goto done;
else if (!tlen)
goto done;
goto done;
else if (!tlen)
goto done;
@@
-1562,14
+1568,12
@@
int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
skb_walk_frags(skb, frag_iter) {
if (!tlen)
break;
skb_walk_frags(skb, frag_iter) {
if (!tlen)
break;
- if (__skb_splice_bits(frag_iter, &offset, &tlen, &spd, sk))
+ if (__skb_splice_bits(frag_iter,
pipe,
&offset, &tlen, &spd, sk))
break;
}
done:
if (spd.nr_pages) {
break;
}
done:
if (spd.nr_pages) {
- int ret;
-
/*
* Drop the socket lock, otherwise we have reverse
* locking dependencies between sk_lock and i_mutex
/*
* Drop the socket lock, otherwise we have reverse
* locking dependencies between sk_lock and i_mutex
@@
-1582,10
+1586,10
@@
done:
release_sock(sk);
ret = splice_to_pipe(pipe, &spd);
lock_sock(sk);
release_sock(sk);
ret = splice_to_pipe(pipe, &spd);
lock_sock(sk);
- return ret;
}
}
- return 0;
+ splice_shrink_spd(pipe, &spd);
+ return ret;
}
/**
}
/**