diff options
| author | Tom Zanussi <zanussi@comcast.net> | 2008-05-09 07:28:36 -0400 |
|---|---|---|
| committer | Jens Axboe <jens.axboe@oracle.com> | 2008-05-28 08:49:27 -0400 |
| commit | a82c53a0e3f57f02782330372b7adad67b417645 (patch) | |
| tree | 3a4e65ab1a2420f8fc5d0091a6992d6f7e430ad8 | |
| parent | 1ec7d99c16e69a9ed8ffeaa6c1846025b84bebad (diff) | |
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>
| -rw-r--r-- | fs/splice.c | 12 | ||||
| -rw-r--r-- | kernel/relay.c | 2 |
2 files changed, 9 insertions, 5 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, | |||
| 983 | 983 | ||
| 984 | while (len) { | 984 | while (len) { |
| 985 | size_t read_len; | 985 | size_t read_len; |
| 986 | loff_t pos = sd->pos; | 986 | loff_t pos = sd->pos, prev_pos = pos; |
| 987 | 987 | ||
| 988 | ret = do_splice_to(in, &pos, pipe, len, flags); | 988 | ret = do_splice_to(in, &pos, pipe, len, flags); |
| 989 | if (unlikely(ret <= 0)) | 989 | if (unlikely(ret <= 0)) |
| @@ -998,15 +998,19 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, | |||
| 998 | * could get stuck data in the internal pipe: | 998 | * could get stuck data in the internal pipe: |
| 999 | */ | 999 | */ |
| 1000 | ret = actor(pipe, sd); | 1000 | ret = actor(pipe, sd); |
| 1001 | if (unlikely(ret <= 0)) | 1001 | if (unlikely(ret <= 0)) { |
| 1002 | sd->pos = prev_pos; | ||
| 1002 | goto out_release; | 1003 | goto out_release; |
| 1004 | } | ||
| 1003 | 1005 | ||
| 1004 | bytes += ret; | 1006 | bytes += ret; |
| 1005 | len -= ret; | 1007 | len -= ret; |
| 1006 | sd->pos = pos; | 1008 | sd->pos = pos; |
| 1007 | 1009 | ||
| 1008 | if (ret < read_len) | 1010 | if (ret < read_len) { |
| 1011 | sd->pos = prev_pos + ret; | ||
| 1009 | goto out_release; | 1012 | goto out_release; |
| 1013 | } | ||
| 1010 | } | 1014 | } |
| 1011 | 1015 | ||
| 1012 | done: | 1016 | done: |
| @@ -1072,7 +1076,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | |||
| 1072 | 1076 | ||
| 1073 | ret = splice_direct_to_actor(in, &sd, direct_splice_actor); | 1077 | ret = splice_direct_to_actor(in, &sd, direct_splice_actor); |
| 1074 | if (ret > 0) | 1078 | if (ret > 0) |
| 1075 | *ppos += ret; | 1079 | *ppos = sd.pos; |
| 1076 | 1080 | ||
| 1077 | return ret; | 1081 | return ret; |
| 1078 | } | 1082 | } |
diff --git a/kernel/relay.c b/kernel/relay.c index bc24dcdc570f..7de644cdec43 100644 --- a/kernel/relay.c +++ b/kernel/relay.c | |||
| @@ -1191,7 +1191,7 @@ static ssize_t relay_file_splice_read(struct file *in, | |||
| 1191 | ret = 0; | 1191 | ret = 0; |
| 1192 | spliced = 0; | 1192 | spliced = 0; |
| 1193 | 1193 | ||
| 1194 | while (len) { | 1194 | while (len && !spliced) { |
| 1195 | ret = subbuf_splice_actor(in, ppos, pipe, len, flags, &nonpad_ret); | 1195 | ret = subbuf_splice_actor(in, ppos, pipe, len, flags, &nonpad_ret); |
| 1196 | if (ret < 0) | 1196 | if (ret < 0) |
| 1197 | break; | 1197 | break; |
