summaryrefslogtreecommitdiff
path: root/fs/splice.c
diff options
context:
space:
mode:
authorTom Zanussi <zanussi@comcast.net>2008-05-09 13:28:36 +0200
committerJens Axboe <jens.axboe@oracle.com>2008-05-28 14:49:27 +0200
commita82c53a0e3f57f02782330372b7adad67b417645 (patch)
tree3a4e65ab1a2420f8fc5d0091a6992d6f7e430ad8 /fs/splice.c
parent1ec7d99c16e69a9ed8ffeaa6c1846025b84bebad (diff)
downloadlwn-a82c53a0e3f57f02782330372b7adad67b417645.tar.gz
lwn-a82c53a0e3f57f02782330372b7adad67b417645.zip
splice: fix sendfile() issue with relay
Splice isn't always incrementing the ppos correctly, which broke relay splice. Signed-off-by: Tom Zanussi <zanussi@comcast.net> Tested-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 78150038b584..a048ad2130c3 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -983,7 +983,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
while (len) {
size_t read_len;
- loff_t pos = sd->pos;
+ loff_t pos = sd->pos, prev_pos = pos;
ret = do_splice_to(in, &pos, pipe, len, flags);
if (unlikely(ret <= 0))
@@ -998,15 +998,19 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
* could get stuck data in the internal pipe:
*/
ret = actor(pipe, sd);
- if (unlikely(ret <= 0))
+ if (unlikely(ret <= 0)) {
+ sd->pos = prev_pos;
goto out_release;
+ }
bytes += ret;
len -= ret;
sd->pos = pos;
- if (ret < read_len)
+ if (ret < read_len) {
+ sd->pos = prev_pos + ret;
goto out_release;
+ }
}
done:
@@ -1072,7 +1076,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
ret = splice_direct_to_actor(in, &sd, direct_splice_actor);
if (ret > 0)
- *ppos += ret;
+ *ppos = sd.pos;
return ret;
}