Commit 1563ac75 authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim
Browse files

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: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 78682f79
Loading
Loading
Loading
Loading
+8 −8
Original line number Original line Diff line number Diff line
@@ -500,14 +500,14 @@ repeat:


	/* wait for read completion */
	/* wait for read completion */
	lock_page(page);
	lock_page(page);
	if (unlikely(!PageUptodate(page))) {
		f2fs_put_page(page, 1);
		return ERR_PTR(-EIO);
	}
	if (unlikely(page->mapping != mapping)) {
	if (unlikely(page->mapping != mapping)) {
		f2fs_put_page(page, 1);
		f2fs_put_page(page, 1);
		goto repeat;
		goto repeat;
	}
	}
	if (unlikely(!PageUptodate(page))) {
		f2fs_put_page(page, 1);
		return ERR_PTR(-EIO);
	}
	return page;
	return page;
}
}


@@ -1647,14 +1647,14 @@ repeat:
		__submit_bio(sbi, READ_SYNC, bio, DATA);
		__submit_bio(sbi, READ_SYNC, bio, DATA);


		lock_page(page);
		lock_page(page);
		if (unlikely(!PageUptodate(page))) {
			err = -EIO;
			goto fail;
		}
		if (unlikely(page->mapping != mapping)) {
		if (unlikely(page->mapping != mapping)) {
			f2fs_put_page(page, 1);
			f2fs_put_page(page, 1);
			goto repeat;
			goto repeat;
		}
		}
		if (unlikely(!PageUptodate(page))) {
			err = -EIO;
			goto fail;
		}
	}
	}
out_update:
out_update:
	SetPageUptodate(page);
	SetPageUptodate(page);
+2 −2
Original line number Original line Diff line number Diff line
@@ -593,11 +593,11 @@ static void move_encrypted_block(struct inode *inode, block_t bidx)
	/* write page */
	/* write page */
	lock_page(fio.encrypted_page);
	lock_page(fio.encrypted_page);


	if (unlikely(!PageUptodate(fio.encrypted_page))) {
	if (unlikely(fio.encrypted_page->mapping != META_MAPPING(fio.sbi))) {
		err = -EIO;
		err = -EIO;
		goto put_page_out;
		goto put_page_out;
	}
	}
	if (unlikely(fio.encrypted_page->mapping != META_MAPPING(fio.sbi))) {
	if (unlikely(!PageUptodate(fio.encrypted_page))) {
		err = -EIO;
		err = -EIO;
		goto put_page_out;
		goto put_page_out;
	}
	}
+3 −3
Original line number Original line Diff line number Diff line
@@ -1146,13 +1146,13 @@ repeat:


	lock_page(page);
	lock_page(page);


	if (unlikely(!PageUptodate(page)))
		goto out_err;

	if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
	if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
		f2fs_put_page(page, 1);
		f2fs_put_page(page, 1);
		goto repeat;
		goto repeat;
	}
	}

	if (unlikely(!PageUptodate(page)))
		goto out_err;
page_hit:
page_hit:
	if(unlikely(nid != nid_of_node(page))) {
	if(unlikely(nid != nid_of_node(page))) {
		f2fs_bug_on(sbi, 1);
		f2fs_bug_on(sbi, 1);