aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-06-11 14:31:05 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-06-11 14:31:05 -0400
commit5212c555be332fc95982077e6cdc7bb6cb5fff5f (patch)
tree44907e3427949462dcc54ae762cc49ae8e9571f0 /fs
parent845a2fdcbd5bc5b9f652201ee95c825827a1d521 (diff)
parent620a324b744a7d66c3c45a83042f8e7fc9fc5a04 (diff)
Merge branch 'splice-2.6.22' of git://git.kernel.dk/data/git/linux-2.6-block
* 'splice-2.6.22' of git://git.kernel.dk/data/git/linux-2.6-block: splice: __generic_file_splice_read: fix read/truncate race splice: __generic_file_splice_read: fix i_size_read() length checks splice: move balance_dirty_pages_ratelimited() outside of splice actor pipe: move pipe_inode_info structure decleration up before it's used splice: remove do_splice_direct() symbol export splice: move inode size check into generic_file_splice_read()
Diffstat (limited to 'fs')
-rw-r--r--fs/splice.c70
1 files changed, 35 insertions, 35 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 12f28281d2b1..cb211360273a 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -272,7 +272,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
272 struct page *page; 272 struct page *page;
273 pgoff_t index, end_index; 273 pgoff_t index, end_index;
274 loff_t isize; 274 loff_t isize;
275 size_t total_len;
276 int error, page_nr; 275 int error, page_nr;
277 struct splice_pipe_desc spd = { 276 struct splice_pipe_desc spd = {
278 .pages = pages, 277 .pages = pages,
@@ -298,7 +297,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
298 * Now fill in the holes: 297 * Now fill in the holes:
299 */ 298 */
300 error = 0; 299 error = 0;
301 total_len = 0;
302 300
303 /* 301 /*
304 * Lookup the (hopefully) full range of pages we need. 302 * Lookup the (hopefully) full range of pages we need.
@@ -415,43 +413,47 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
415 413
416 break; 414 break;
417 } 415 }
416 }
417fill_it:
418 /*
419 * i_size must be checked after PageUptodate.
420 */
421 isize = i_size_read(mapping->host);
422 end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
423 if (unlikely(!isize || index > end_index))
424 break;
425
426 /*
427 * if this is the last page, see if we need to shrink
428 * the length and stop
429 */
430 if (end_index == index) {
431 unsigned int plen;
418 432
419 /* 433 /*
420 * i_size must be checked after ->readpage(). 434 * max good bytes in this page
421 */ 435 */
422 isize = i_size_read(mapping->host); 436 plen = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
423 end_index = (isize - 1) >> PAGE_CACHE_SHIFT; 437 if (plen <= loff)
424 if (unlikely(!isize || index > end_index))
425 break; 438 break;
426 439
427 /* 440 /*
428 * if this is the last page, see if we need to shrink 441 * force quit after adding this page
429 * the length and stop
430 */ 442 */
431 if (end_index == index) { 443 this_len = min(this_len, plen - loff);
432 loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK); 444 len = this_len;
433 if (total_len + loff > isize)
434 break;
435 /*
436 * force quit after adding this page
437 */
438 len = this_len;
439 this_len = min(this_len, loff);
440 loff = 0;
441 }
442 } 445 }
443fill_it: 446
444 partial[page_nr].offset = loff; 447 partial[page_nr].offset = loff;
445 partial[page_nr].len = this_len; 448 partial[page_nr].len = this_len;
446 len -= this_len; 449 len -= this_len;
447 total_len += this_len;
448 loff = 0; 450 loff = 0;
449 spd.nr_pages++; 451 spd.nr_pages++;
450 index++; 452 index++;
451 } 453 }
452 454
453 /* 455 /*
454 * Release any pages at the end, if we quit early. 'i' is how far 456 * Release any pages at the end, if we quit early. 'page_nr' is how far
455 * we got, 'nr_pages' is how many pages are in the map. 457 * we got, 'nr_pages' is how many pages are in the map.
456 */ 458 */
457 while (page_nr < nr_pages) 459 while (page_nr < nr_pages)
@@ -478,10 +480,18 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
478{ 480{
479 ssize_t spliced; 481 ssize_t spliced;
480 int ret; 482 int ret;
483 loff_t isize, left;
484
485 isize = i_size_read(in->f_mapping->host);
486 if (unlikely(*ppos >= isize))
487 return 0;
488
489 left = isize - *ppos;
490 if (unlikely(left < len))
491 len = left;
481 492
482 ret = 0; 493 ret = 0;
483 spliced = 0; 494 spliced = 0;
484
485 while (len) { 495 while (len) {
486 ret = __generic_file_splice_read(in, ppos, pipe, len, flags); 496 ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
487 497
@@ -644,7 +654,6 @@ find_page:
644 * accessed, we are now done! 654 * accessed, we are now done!
645 */ 655 */
646 mark_page_accessed(page); 656 mark_page_accessed(page);
647 balance_dirty_pages_ratelimited(mapping);
648out: 657out:
649 page_cache_release(page); 658 page_cache_release(page);
650 unlock_page(page); 659 unlock_page(page);
@@ -815,6 +824,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
815 if (err) 824 if (err)
816 ret = err; 825 ret = err;
817 } 826 }
827 balance_dirty_pages_ratelimited(mapping);
818 } 828 }
819 829
820 return ret; 830 return ret;
@@ -868,6 +878,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
868 if (err) 878 if (err)
869 ret = err; 879 ret = err;
870 } 880 }
881 balance_dirty_pages_ratelimited(mapping);
871 } 882 }
872 883
873 return ret; 884 return ret;
@@ -922,7 +933,6 @@ static long do_splice_to(struct file *in, loff_t *ppos,
922 struct pipe_inode_info *pipe, size_t len, 933 struct pipe_inode_info *pipe, size_t len,
923 unsigned int flags) 934 unsigned int flags)
924{ 935{
925 loff_t isize, left;
926 int ret; 936 int ret;
927 937
928 if (unlikely(!in->f_op || !in->f_op->splice_read)) 938 if (unlikely(!in->f_op || !in->f_op->splice_read))
@@ -935,14 +945,6 @@ static long do_splice_to(struct file *in, loff_t *ppos,
935 if (unlikely(ret < 0)) 945 if (unlikely(ret < 0))
936 return ret; 946 return ret;
937 947
938 isize = i_size_read(in->f_mapping->host);
939 if (unlikely(*ppos >= isize))
940 return 0;
941
942 left = isize - *ppos;
943 if (unlikely(left < len))
944 len = left;
945
946 return in->f_op->splice_read(in, ppos, pipe, len, flags); 948 return in->f_op->splice_read(in, ppos, pipe, len, flags);
947} 949}
948 950
@@ -1058,8 +1060,6 @@ out_release:
1058 return ret; 1060 return ret;
1059} 1061}
1060 1062
1061EXPORT_SYMBOL(do_splice_direct);
1062
1063/* 1063/*
1064 * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same 1064 * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
1065 * location, so checking ->i_pipe is not enough to verify that this is a 1065 * location, so checking ->i_pipe is not enough to verify that this is a