f2fs: fix to detect truncation prior rather than EIO during read
authorChao Yu <yuchao0@huawei.com>
Sun, 3 Jul 2016 14:05:12 +0000 (22:05 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Fri, 8 Jul 2016 17:33:25 +0000 (10:33 -0700)
In procedure of synchonized read, after sending out the read request, reader
will try to lock the page for waiting device to finish the read jobs and
unlock the page, but meanwhile, truncater will race with reader, so after
reader get lock of the page, it should check page's mapping to detect
whether someone has truncated the page in advance, then reader has the
chance to do the retry if truncation was done, otherwise read can be failed
due to previous condition check.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/data.c
fs/f2fs/gc.c
fs/f2fs/node.c

index 53fae38009d3346d1edb094b704d292dd51008df..3d93cf1841144fa34bfa6e455ea69ea5af1ec256 100644 (file)
@@ -500,14 +500,14 @@ repeat:
 
        /* wait for read completion */
        lock_page(page);
-       if (unlikely(!PageUptodate(page))) {
-               f2fs_put_page(page, 1);
-               return ERR_PTR(-EIO);
-       }
        if (unlikely(page->mapping != mapping)) {
                f2fs_put_page(page, 1);
                goto repeat;
        }
+       if (unlikely(!PageUptodate(page))) {
+               f2fs_put_page(page, 1);
+               return ERR_PTR(-EIO);
+       }
        return page;
 }
 
@@ -1647,14 +1647,14 @@ repeat:
                __submit_bio(sbi, READ_SYNC, bio, DATA);
 
                lock_page(page);
-               if (unlikely(!PageUptodate(page))) {
-                       err = -EIO;
-                       goto fail;
-               }
                if (unlikely(page->mapping != mapping)) {
                        f2fs_put_page(page, 1);
                        goto repeat;
                }
+               if (unlikely(!PageUptodate(page))) {
+                       err = -EIO;
+                       goto fail;
+               }
        }
 out_update:
        SetPageUptodate(page);
index e1d274cdecb8d3c0780ca47a1d81525e3e459b4e..c9602d0dc57ab05bf32f27305407eb68eb44e04a 100644 (file)
@@ -593,11 +593,11 @@ static void move_encrypted_block(struct inode *inode, block_t bidx)
        /* write page */
        lock_page(fio.encrypted_page);
 
-       if (unlikely(!PageUptodate(fio.encrypted_page))) {
+       if (unlikely(fio.encrypted_page->mapping != META_MAPPING(fio.sbi))) {
                err = -EIO;
                goto put_page_out;
        }
-       if (unlikely(fio.encrypted_page->mapping != META_MAPPING(fio.sbi))) {
+       if (unlikely(!PageUptodate(fio.encrypted_page))) {
                err = -EIO;
                goto put_page_out;
        }
index 729fb1eb86cedbd36f4d36584732346ef0f11f99..69171ce9b4b14ca95f44cfaddab42d97f9ea4859 100644 (file)
@@ -1146,13 +1146,13 @@ repeat:
 
        lock_page(page);
 
-       if (unlikely(!PageUptodate(page)))
-               goto out_err;
-
        if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
                f2fs_put_page(page, 1);
                goto repeat;
        }
+
+       if (unlikely(!PageUptodate(page)))
+               goto out_err;
 page_hit:
        if(unlikely(nid != nid_of_node(page))) {
                f2fs_bug_on(sbi, 1);