Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=61e930a904966cc37e0a3404276f0b73037e57ca
Commit:     61e930a904966cc37e0a3404276f0b73037e57ca
Parent:     4fa4d23fa20de67df919030c1216295664866ad7
Author:     Trond Myklebust <[EMAIL PROTECTED]>
AuthorDate: Thu Oct 18 17:08:05 2007 -0400
Committer:  Trond Myklebust <[EMAIL PROTECTED]>
CommitDate: Fri Oct 19 17:18:57 2007 -0400

    NFS: Fix a writeback race...
    
    This patch fixes a regression that was introduced by commit
    44dd151d5c21234cc534c47d7382f5c28c3143cd
    
    We cannot zero the user page in nfs_mark_uptodate() any more, since
    
      a) We'd be modifying the page without holding the page lock
      b) We can race with other updates of the page, most notably
         because of the call to nfs_wb_page() in nfs_writepage_setup().
    
    Instead, we do the zeroing in nfs_update_request() if we see that we're
    creating a request that might potentially be marked as up to date.
    
    Thanks to Olivier Paquet for reporting the bug and providing a test-case.
    
    Signed-off-by: Trond Myklebust <[EMAIL PROTECTED]>
---
 fs/nfs/write.c |   17 +++++++++++++----
 1 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 0cf9d1c..89527a4 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -174,8 +174,6 @@ static void nfs_mark_uptodate(struct page *page, unsigned 
int base, unsigned int
                return;
        if (count != nfs_page_length(page))
                return;
-       if (count != PAGE_CACHE_SIZE)
-               zero_user_page(page, count, PAGE_CACHE_SIZE - count, KM_USER0);
        SetPageUptodate(page);
 }
 
@@ -627,7 +625,8 @@ static struct nfs_page * nfs_update_request(struct 
nfs_open_context* ctx,
                                return ERR_PTR(error);
                        }
                        spin_unlock(&inode->i_lock);
-                       return new;
+                       req = new;
+                       goto zero_page;
                }
                spin_unlock(&inode->i_lock);
 
@@ -655,13 +654,23 @@ static struct nfs_page * nfs_update_request(struct 
nfs_open_context* ctx,
        if (offset < req->wb_offset) {
                req->wb_offset = offset;
                req->wb_pgbase = offset;
-               req->wb_bytes = rqend - req->wb_offset;
+               req->wb_bytes = max(end, rqend) - req->wb_offset;
+               goto zero_page;
        }
 
        if (end > rqend)
                req->wb_bytes = end - req->wb_offset;
 
        return req;
+zero_page:
+       /* If this page might potentially be marked as up to date,
+        * then we need to zero any uninitalised data. */
+       if (req->wb_pgbase == 0 && req->wb_bytes != PAGE_CACHE_SIZE
+                       && !PageUptodate(req->wb_page))
+               zero_user_page(req->wb_page, req->wb_bytes,
+                               PAGE_CACHE_SIZE - req->wb_bytes,
+                               KM_USER0);
+       return req;
 }
 
 int nfs_flush_incompatible(struct file *file, struct page *page)
-
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