Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=620a324b744a7d66c3c45a83042f8e7fc9fc5a04
Commit:     620a324b744a7d66c3c45a83042f8e7fc9fc5a04
Parent:     475ecade683566b19ebb84972de864039ac5fce3
Author:     Jens Axboe <[EMAIL PROTECTED]>
AuthorDate: Thu Jun 7 09:39:42 2007 +0200
Committer:  Jens Axboe <[EMAIL PROTECTED]>
CommitDate: Fri Jun 8 08:34:11 2007 +0200

    splice: __generic_file_splice_read: fix read/truncate race
    
    Original patch and description from Neil Brown <[EMAIL PROTECTED]>,
    merged and adapted to splice branch by me. Neils text follows:
    
    __generic_file_splice_read() currently samples the i_size at the start
    and doesn't do so again unless it needs to call ->readpage to load
    a page.  After ->readpage it has to re-sample i_size as a truncate
    may have caused that page to be filled with zeros, and the read()
    call should not see these.
    
    However there are other activities that might cause ->readpage to be
    called on a page between the time that __generic_file_splice_read()
    samples i_size and when it finds that it has an uptodate page. These
    include at least read-ahead and possibly another thread performing a
    read
    
    So we must sample i_size *after* it has an uptodate page.  Thus the
    current sampling at the start and after a read can be replaced with a
    sampling before page addition into spd.
    
    Signed-off-by: Jens Axboe <[EMAIL PROTECTED]>
---
 fs/splice.c |   46 +++++++++++++++++++++++-----------------------
 1 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/fs/splice.c b/fs/splice.c
index 123fcdb..cb21136 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -413,37 +413,37 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
 
                                break;
                        }
+               }
+fill_it:
+               /*
+                * i_size must be checked after PageUptodate.
+                */
+               isize = i_size_read(mapping->host);
+               end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+               if (unlikely(!isize || index > end_index))
+                       break;
+
+               /*
+                * if this is the last page, see if we need to shrink
+                * the length and stop
+                */
+               if (end_index == index) {
+                       unsigned int plen;
 
                        /*
-                        * i_size must be checked after ->readpage().
+                        * max good bytes in this page
                         */
-                       isize = i_size_read(mapping->host);
-                       end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
-                       if (unlikely(!isize || index > end_index))
+                       plen = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+                       if (plen <= loff)
                                break;
 
                        /*
-                        * if this is the last page, see if we need to shrink
-                        * the length and stop
+                        * force quit after adding this page
                         */
-                       if (end_index == index) {
-                               unsigned int plen;
-
-                               /*
-                                * max good bytes in this page
-                                */
-                               plen = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
-                               if (plen <= loff)
-                                       break;
-
-                               /*
-                                * force quit after adding this page
-                                */
-                               this_len = min(this_len, plen - loff);
-                               len = this_len;
-                       }
+                       this_len = min(this_len, plen - loff);
+                       len = this_len;
                }
-fill_it:
+
                partial[page_nr].offset = loff;
                partial[page_nr].len = this_len;
                len -= this_len;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to