diff options
author | Jaegeuk Kim <jaegeuk@kernel.org> | 2018-08-22 21:18:00 -0700 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@google.com> | 2018-11-02 18:36:22 +0000 |
commit | 641303def9a59cbf05c4068df5c30f0bb538dee0 (patch) | |
tree | c79a1ac73ad7cfeb6a6ea1fb766d4b0fb556a6a6 | |
parent | 61a39ab76df8376fb92e256e3a99835185ba8267 (diff) |
UPSTREAM: f2fs: avoid wrong decrypted data from diskandroid-9.0.0_r0.43
Cherry-pick from upstream:
commit 0ded69f632bb ("f2fs: avoid wrong decrypted data from disk")
1. Create a file in an encrypted directory
2. Do GC & drop caches
3. Read stale data before its bio for metapage was not issued yet
Bug: 115990430
Change-Id: Ibe95bbf440e3db54f9790a2f2af3a6c513c38735
Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r-- | fs/f2fs/data.c | 18 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 2 | ||||
-rw-r--r-- | fs/f2fs/file.c | 3 | ||||
-rw-r--r-- | fs/f2fs/segment.c | 6 |
4 files changed, 17 insertions, 12 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index f2cba440773b..d7d018848e37 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -606,9 +606,6 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, ctx->bio = bio; ctx->enabled_steps = post_read_steps; bio->bi_private = ctx; - - /* wait the page to be moved by cleaning */ - f2fs_wait_on_block_writeback(sbi, blkaddr); } return bio; @@ -626,6 +623,9 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page, if (f2fs_may_encrypt_bio(inode, NULL)) fscrypt_set_ice_dun(inode, bio, PG_DUN(inode, page)); + /* wait for GCed page writeback via META_MAPPING */ + f2fs_wait_on_block_writeback(inode, blkaddr); + if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { bio_put(bio); return -EFAULT; @@ -1587,6 +1587,12 @@ submit_and_realloc: fscrypt_set_ice_dun(inode, bio, dun); } + /* + * If the page is under writeback, we need to wait for + * its completion to see the correct decrypted data. + */ + f2fs_wait_on_block_writeback(inode, block_nr); + if (bio_add_page(bio, page, blocksize, 0) < blocksize) goto submit_and_realloc; @@ -1653,7 +1659,7 @@ static int encrypt_one_page(struct f2fs_io_info *fio) return 0; /* wait for GCed page writeback via META_MAPPING */ - f2fs_wait_on_block_writeback(fio->sbi, fio->old_blkaddr); + f2fs_wait_on_block_writeback(inode, fio->old_blkaddr); retry_encrypt: if (fscrypt_using_hardware_encryption(inode)) @@ -2382,10 +2388,6 @@ repeat: f2fs_wait_on_page_writeback(page, DATA, false); - /* wait for GCed page writeback via META_MAPPING */ - if (f2fs_post_read_required(inode)) - f2fs_wait_on_block_writeback(sbi, blkaddr); - if (len == PAGE_SIZE || PageUptodate(page)) return 0; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index dc89bae066ea..702aa181851a 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2839,7 +2839,7 @@ void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, struct f2fs_io_info *fio, bool add_list); void f2fs_wait_on_page_writeback(struct page *page, enum page_type type, bool ordered); -void f2fs_wait_on_block_writeback(struct f2fs_sb_info *sbi, block_t blkaddr); +void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr); void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk); void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk); int lookup_journal_in_cursum(struct f2fs_journal *journal, int type, diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 5a39adf9f804..e62fb40c03d8 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -113,8 +113,7 @@ mapped: f2fs_wait_on_page_writeback(page, DATA, false); /* wait for GCed page writeback via META_MAPPING */ - if (f2fs_post_read_required(inode)) - f2fs_wait_on_block_writeback(sbi, dn.data_blkaddr); + f2fs_wait_on_block_writeback(inode, dn.data_blkaddr); out_sem: up_read(&F2FS_I(inode)->i_mmap_sem); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 4fa2efadf5e7..5062c02e73dc 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2946,10 +2946,14 @@ void f2fs_wait_on_page_writeback(struct page *page, } } -void f2fs_wait_on_block_writeback(struct f2fs_sb_info *sbi, block_t blkaddr) +void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr) { + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct page *cpage; + if (!f2fs_post_read_required(inode)) + return; + if (blkaddr == NEW_ADDR || blkaddr == NULL_ADDR) return; |