diff options
Diffstat (limited to 'fs/splice.c')
-rw-r--r-- | fs/splice.c | 83 |
1 files changed, 39 insertions, 44 deletions
diff --git a/fs/splice.c b/fs/splice.c index ed2ce995475c..0a0973218084 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/syscalls.h> | 29 | #include <linux/syscalls.h> |
30 | #include <linux/uio.h> | 30 | #include <linux/uio.h> |
31 | #include <linux/security.h> | ||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * Attempt to steal a page from a pipe buffer. This should perhaps go into | 34 | * Attempt to steal a page from a pipe buffer. This should perhaps go into |
@@ -264,7 +265,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
264 | unsigned int flags) | 265 | unsigned int flags) |
265 | { | 266 | { |
266 | struct address_space *mapping = in->f_mapping; | 267 | struct address_space *mapping = in->f_mapping; |
267 | unsigned int loff, nr_pages; | 268 | unsigned int loff, nr_pages, req_pages; |
268 | struct page *pages[PIPE_BUFFERS]; | 269 | struct page *pages[PIPE_BUFFERS]; |
269 | struct partial_page partial[PIPE_BUFFERS]; | 270 | struct partial_page partial[PIPE_BUFFERS]; |
270 | struct page *page; | 271 | struct page *page; |
@@ -280,28 +281,24 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
280 | 281 | ||
281 | index = *ppos >> PAGE_CACHE_SHIFT; | 282 | index = *ppos >> PAGE_CACHE_SHIFT; |
282 | loff = *ppos & ~PAGE_CACHE_MASK; | 283 | loff = *ppos & ~PAGE_CACHE_MASK; |
283 | nr_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 284 | req_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
284 | 285 | nr_pages = min(req_pages, (unsigned)PIPE_BUFFERS); | |
285 | if (nr_pages > PIPE_BUFFERS) | ||
286 | nr_pages = PIPE_BUFFERS; | ||
287 | |||
288 | /* | ||
289 | * Don't try to 2nd guess the read-ahead logic, call into | ||
290 | * page_cache_readahead() like the page cache reads would do. | ||
291 | */ | ||
292 | page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages); | ||
293 | 286 | ||
294 | /* | 287 | /* |
295 | * Lookup the (hopefully) full range of pages we need. | 288 | * Lookup the (hopefully) full range of pages we need. |
296 | */ | 289 | */ |
297 | spd.nr_pages = find_get_pages_contig(mapping, index, nr_pages, pages); | 290 | spd.nr_pages = find_get_pages_contig(mapping, index, nr_pages, pages); |
291 | index += spd.nr_pages; | ||
298 | 292 | ||
299 | /* | 293 | /* |
300 | * If find_get_pages_contig() returned fewer pages than we needed, | 294 | * If find_get_pages_contig() returned fewer pages than we needed, |
301 | * allocate the rest and fill in the holes. | 295 | * readahead/allocate the rest and fill in the holes. |
302 | */ | 296 | */ |
297 | if (spd.nr_pages < nr_pages) | ||
298 | page_cache_sync_readahead(mapping, &in->f_ra, in, | ||
299 | index, req_pages - spd.nr_pages); | ||
300 | |||
303 | error = 0; | 301 | error = 0; |
304 | index += spd.nr_pages; | ||
305 | while (spd.nr_pages < nr_pages) { | 302 | while (spd.nr_pages < nr_pages) { |
306 | /* | 303 | /* |
307 | * Page could be there, find_get_pages_contig() breaks on | 304 | * Page could be there, find_get_pages_contig() breaks on |
@@ -310,12 +307,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
310 | page = find_get_page(mapping, index); | 307 | page = find_get_page(mapping, index); |
311 | if (!page) { | 308 | if (!page) { |
312 | /* | 309 | /* |
313 | * Make sure the read-ahead engine is notified | ||
314 | * about this failure. | ||
315 | */ | ||
316 | handle_ra_miss(mapping, &in->f_ra, index); | ||
317 | |||
318 | /* | ||
319 | * page didn't exist, allocate one. | 310 | * page didn't exist, allocate one. |
320 | */ | 311 | */ |
321 | page = page_cache_alloc_cold(mapping); | 312 | page = page_cache_alloc_cold(mapping); |
@@ -360,6 +351,10 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
360 | this_len = min_t(unsigned long, len, PAGE_CACHE_SIZE - loff); | 351 | this_len = min_t(unsigned long, len, PAGE_CACHE_SIZE - loff); |
361 | page = pages[page_nr]; | 352 | page = pages[page_nr]; |
362 | 353 | ||
354 | if (PageReadahead(page)) | ||
355 | page_cache_async_readahead(mapping, &in->f_ra, in, | ||
356 | page, index, req_pages - page_nr); | ||
357 | |||
363 | /* | 358 | /* |
364 | * If the page isn't uptodate, we may need to start io on it | 359 | * If the page isn't uptodate, we may need to start io on it |
365 | */ | 360 | */ |
@@ -452,6 +447,7 @@ fill_it: | |||
452 | */ | 447 | */ |
453 | while (page_nr < nr_pages) | 448 | while (page_nr < nr_pages) |
454 | page_cache_release(pages[page_nr++]); | 449 | page_cache_release(pages[page_nr++]); |
450 | in->f_ra.prev_index = index; | ||
455 | 451 | ||
456 | if (spd.nr_pages) | 452 | if (spd.nr_pages) |
457 | return splice_to_pipe(pipe, &spd); | 453 | return splice_to_pipe(pipe, &spd); |
@@ -491,7 +487,7 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, | |||
491 | 487 | ||
492 | ret = 0; | 488 | ret = 0; |
493 | spliced = 0; | 489 | spliced = 0; |
494 | while (len) { | 490 | while (len && !spliced) { |
495 | ret = __generic_file_splice_read(in, ppos, pipe, len, flags); | 491 | ret = __generic_file_splice_read(in, ppos, pipe, len, flags); |
496 | 492 | ||
497 | if (ret < 0) | 493 | if (ret < 0) |
@@ -598,7 +594,7 @@ find_page: | |||
598 | ret = add_to_page_cache_lru(page, mapping, index, | 594 | ret = add_to_page_cache_lru(page, mapping, index, |
599 | GFP_KERNEL); | 595 | GFP_KERNEL); |
600 | if (unlikely(ret)) | 596 | if (unlikely(ret)) |
601 | goto out; | 597 | goto out_release; |
602 | } | 598 | } |
603 | 599 | ||
604 | ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len); | 600 | ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len); |
@@ -654,8 +650,9 @@ find_page: | |||
654 | */ | 650 | */ |
655 | mark_page_accessed(page); | 651 | mark_page_accessed(page); |
656 | out: | 652 | out: |
657 | page_cache_release(page); | ||
658 | unlock_page(page); | 653 | unlock_page(page); |
654 | out_release: | ||
655 | page_cache_release(page); | ||
659 | out_ret: | 656 | out_ret: |
660 | return ret; | 657 | return ret; |
661 | } | 658 | } |
@@ -961,6 +958,10 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, | |||
961 | if (unlikely(ret < 0)) | 958 | if (unlikely(ret < 0)) |
962 | return ret; | 959 | return ret; |
963 | 960 | ||
961 | ret = security_file_permission(out, MAY_WRITE); | ||
962 | if (unlikely(ret < 0)) | ||
963 | return ret; | ||
964 | |||
964 | return out->f_op->splice_write(pipe, out, ppos, len, flags); | 965 | return out->f_op->splice_write(pipe, out, ppos, len, flags); |
965 | } | 966 | } |
966 | 967 | ||
@@ -983,6 +984,10 @@ static long do_splice_to(struct file *in, loff_t *ppos, | |||
983 | if (unlikely(ret < 0)) | 984 | if (unlikely(ret < 0)) |
984 | return ret; | 985 | return ret; |
985 | 986 | ||
987 | ret = security_file_permission(in, MAY_READ); | ||
988 | if (unlikely(ret < 0)) | ||
989 | return ret; | ||
990 | |||
986 | return in->f_op->splice_read(in, ppos, pipe, len, flags); | 991 | return in->f_op->splice_read(in, ppos, pipe, len, flags); |
987 | } | 992 | } |
988 | 993 | ||
@@ -1051,15 +1056,11 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, | |||
1051 | sd->flags &= ~SPLICE_F_NONBLOCK; | 1056 | sd->flags &= ~SPLICE_F_NONBLOCK; |
1052 | 1057 | ||
1053 | while (len) { | 1058 | while (len) { |
1054 | size_t read_len, max_read_len; | 1059 | size_t read_len; |
1060 | loff_t pos = sd->pos; | ||
1055 | 1061 | ||
1056 | /* | 1062 | ret = do_splice_to(in, &pos, pipe, len, flags); |
1057 | * Do at most PIPE_BUFFERS pages worth of transfer: | 1063 | if (unlikely(ret <= 0)) |
1058 | */ | ||
1059 | max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE)); | ||
1060 | |||
1061 | ret = do_splice_to(in, &sd->pos, pipe, max_read_len, flags); | ||
1062 | if (unlikely(ret < 0)) | ||
1063 | goto out_release; | 1064 | goto out_release; |
1064 | 1065 | ||
1065 | read_len = ret; | 1066 | read_len = ret; |
@@ -1071,26 +1072,18 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, | |||
1071 | * could get stuck data in the internal pipe: | 1072 | * could get stuck data in the internal pipe: |
1072 | */ | 1073 | */ |
1073 | ret = actor(pipe, sd); | 1074 | ret = actor(pipe, sd); |
1074 | if (unlikely(ret < 0)) | 1075 | if (unlikely(ret <= 0)) |
1075 | goto out_release; | 1076 | goto out_release; |
1076 | 1077 | ||
1077 | bytes += ret; | 1078 | bytes += ret; |
1078 | len -= ret; | 1079 | len -= ret; |
1080 | sd->pos = pos; | ||
1079 | 1081 | ||
1080 | /* | 1082 | if (ret < read_len) |
1081 | * In nonblocking mode, if we got back a short read then | 1083 | goto out_release; |
1082 | * that was due to either an IO error or due to the | ||
1083 | * pagecache entry not being there. In the IO error case | ||
1084 | * the _next_ splice attempt will produce a clean IO error | ||
1085 | * return value (not a short read), so in both cases it's | ||
1086 | * correct to break out of the loop here: | ||
1087 | */ | ||
1088 | if ((flags & SPLICE_F_NONBLOCK) && (read_len < max_read_len)) | ||
1089 | break; | ||
1090 | } | 1084 | } |
1091 | 1085 | ||
1092 | pipe->nrbufs = pipe->curbuf = 0; | 1086 | pipe->nrbufs = pipe->curbuf = 0; |
1093 | |||
1094 | return bytes; | 1087 | return bytes; |
1095 | 1088 | ||
1096 | out_release: | 1089 | out_release: |
@@ -1152,10 +1145,12 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | |||
1152 | .pos = *ppos, | 1145 | .pos = *ppos, |
1153 | .u.file = out, | 1146 | .u.file = out, |
1154 | }; | 1147 | }; |
1155 | size_t ret; | 1148 | long ret; |
1156 | 1149 | ||
1157 | ret = splice_direct_to_actor(in, &sd, direct_splice_actor); | 1150 | ret = splice_direct_to_actor(in, &sd, direct_splice_actor); |
1158 | *ppos = sd.pos; | 1151 | if (ret > 0) |
1152 | *ppos += ret; | ||
1153 | |||
1159 | return ret; | 1154 | return ret; |
1160 | } | 1155 | } |
1161 | 1156 | ||