f2fs: fix to set PageUptodate by f2fs_write_end correctly
authorJaegeuk Kim <jaegeuk@kernel.org>
Tue, 6 Sep 2016 18:02:03 +0000 (11:02 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Thu, 8 Sep 2016 01:53:51 +0000 (18:53 -0700)
Previously, f2fs_write_begin sets PageUptodate all the time. But, when user
tries to update the entire page (i.e., len == PAGE_SIZE), we need to consider
that the page is able to be overwritten partially afterwards.
So, given exact copied variable, f2fs_write_end should handle page's flag
accordingly.

Reported-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/data.c

index 8ffb480935b399fbe08bacdd302cc7beb34cc17c..0ea902ecb71cb0e3c591c9acd0319d827e3b49c7 100644 (file)
@@ -1642,10 +1642,8 @@ repeat:
        if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode))
                f2fs_wait_on_encrypted_page_writeback(sbi, blkaddr);
 
-       if (len == PAGE_SIZE)
-               goto out_update;
-       if (PageUptodate(page))
-               goto out_clear;
+       if (len == PAGE_SIZE || PageUptodate(page))
+               return 0;
 
        if (blkaddr == NEW_ADDR) {
                zero_user_segment(page, 0, PAGE_SIZE);
@@ -1676,11 +1674,8 @@ repeat:
                        goto fail;
                }
        }
-out_update:
        if (!PageUptodate(page))
                SetPageUptodate(page);
-out_clear:
-       clear_cold_data(page);
        return 0;
 
 fail:
@@ -1698,11 +1693,28 @@ static int f2fs_write_end(struct file *file,
 
        trace_f2fs_write_end(inode, pos, len, copied);
 
+       if (!copied)
+               goto unlock_out;
+
+       /*
+        * This should be come from len == PAGE_SIZE, so we need to fill out
+        * zeros in the unwritten remaining space.
+        * The flow was copied from fuse_write_end().
+        */
+       if (!PageUptodate(page)) {
+               size_t endoff = (pos + copied) & ~PAGE_MASK;
+
+               if (endoff)
+                       zero_user_segment(page, endoff, PAGE_SIZE);
+               SetPageUptodate(page);
+       }
+
        set_page_dirty(page);
+       clear_cold_data(page);
 
        if (pos + copied > i_size_read(inode))
                f2fs_i_size_write(inode, pos + copied);
-
+unlock_out:
        f2fs_put_page(page, 1);
        f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
        return copied;
This page took 0.025476 seconds and 5 git commands to generate.