summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChao Yu <yuchao0@huawei.com>2016-07-03 22:05:12 +0800
committerJaegeuk Kim <jaegeuk@kernel.org>2016-07-08 10:33:25 -0700
commit1563ac75e7e45adcdc1271e6bb55fe27a23d4e4e (patch)
tree7b3f921f969550d54ebd4d97e3e922468d2b18c9 /fs
parent78682f79447998369a85f12b6437fa8fdbbdca50 (diff)
downloadlinux-stable-1563ac75e7e45adcdc1271e6bb55fe27a23d4e4e.tar.gz
linux-stable-1563ac75e7e45adcdc1271e6bb55fe27a23d4e4e.tar.bz2
linux-stable-1563ac75e7e45adcdc1271e6bb55fe27a23d4e4e.zip
f2fs: fix to detect truncation prior rather than EIO during read
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/f2fs/data.c16
-rw-r--r--fs/f2fs/gc.c4
-rw-r--r--fs/f2fs/node.c6
3 files changed, 13 insertions, 13 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 53fae38009d3..3d93cf184114 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -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);
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index e1d274cdecb8..c9602d0dc57a 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -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;
}
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 729fb1eb86ce..69171ce9b4b1 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -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);