> -----Original Message----- > From: Jaegeuk Kim [mailto:jaeg...@kernel.org] > Sent: Wednesday, October 14, 2015 12:52 AM > To: Chao Yu > Cc: linux-f2fs-de...@lists.sourceforge.net; linux-kernel@vger.kernel.org > Subject: Re: [PATCH] f2fs crypto: fix racing of accessing encrypted page > among different > competitors > > On Tue, Oct 13, 2015 at 02:01:10PM +0800, Chao Yu wrote: > > > -----Original Message----- > > > From: Jaegeuk Kim [mailto:jaeg...@kernel.org] > > > Sent: Tuesday, October 13, 2015 5:00 AM > > > To: Chao Yu > > > Cc: linux-f2fs-de...@lists.sourceforge.net; linux-kernel@vger.kernel.org > > > Subject: Re: [PATCH] f2fs crypto: fix racing of accessing encrypted page > > > among different > > > competitors > > > > > > On Thu, Oct 08, 2015 at 08:50:39PM +0800, Chao Yu wrote: > > > > >From 0211c6ed82440891b3369851d079f6c69b432b6c Mon Sep 17 00:00:00 2001 > > > > From: Chao Yu <chao2...@samsung.com> > > > > Date: Thu, 8 Oct 2015 13:27:34 +0800 > > > > Subject: [PATCH] f2fs crypto: fix racing of accessing encrypted page > > > > among > > > > different competitors > > > > > > > > Since we use different page cache (normally inode's page cache for R/W > > > > and meta inode's page cache for GC) to cache the same physical block > > > > which is belong to an encrypted inode. Writeback of these two page > > > > cache should be exclusive, but now we didn't handle writeback state > > > > well, so there may be potential racing problem: > > > > > > > > a) > > > > kworker: f2fs_gc: > > > > - f2fs_write_data_pages > > > > - f2fs_write_data_page > > > > - do_write_data_page > > > > - write_data_page > > > > - f2fs_submit_page_mbio > > > > (page#1 in inode's page cache was queued > > > > in f2fs bio cache, and be ready to write > > > > to new blkaddr) > > > > - gc_data_segment > > > > - move_encrypted_block > > > > - pagecache_get_page > > > > (page#2 in meta inode's page > > > > cache > > > > was cached with the invalid > > > > datas > > > > of physical block located in new > > > > blkaddr) > > > > - f2fs_submit_page_mbio > > > > (page#1 was submitted, later, > > > > page#2 > > > > with invalid data will be > > > > submitted) > > > > > > > > b) > > > > f2fs_gc: > > > > - gc_data_segment > > > > - move_encrypted_block > > > > - f2fs_submit_page_mbio > > > > (page#1 in meta inode's page cache was > > > > queued in f2fs bio cache, and be ready > > > > to write to new blkaddr) > > > > user thread: > > > > - f2fs_write_begin > > > > - f2fs_submit_page_bio > > > > (we submit the request to block > > > > layer > > > > to update page#2 in inode's > > > > page cache > > > > with physical block located in > > > > new > > > > blkaddr, so here we may read > > > > gabbage > > > > data from new blkaddr since GC > > > > hasn't > > > > writebacked the page#1 yet) > > > > > > > > This patch fixes above potential racing problem for encrypted inode. > > > > > > > > Signed-off-by: Chao Yu <chao2...@samsung.com> > > > > --- > > > > fs/f2fs/data.c | 20 +++++++++++--------- > > > > fs/f2fs/f2fs.h | 1 + > > > > fs/f2fs/file.c | 5 +++++ > > > > fs/f2fs/gc.c | 13 ++++++++++--- > > > > fs/f2fs/segment.c | 17 +++++++++++++++++ > > > > 5 files changed, 44 insertions(+), 12 deletions(-) > > > > > > > > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c > > > > index 40a0102..d791bd3 100644 > > > > --- a/fs/f2fs/data.c > > > > +++ b/fs/f2fs/data.c > > > > @@ -954,21 +954,14 @@ submit_and_realloc: > > > > > > > > if (f2fs_encrypted_inode(inode) && > > > > S_ISREG(inode->i_mode)) { > > > > - struct page *cpage; > > > > > > > > ctx = f2fs_get_crypto_ctx(inode); > > > > if (IS_ERR(ctx)) > > > > goto set_error_page; > > > > > > > > /* wait the page to be moved by > > > > cleaning */ > > > > - cpage = find_lock_page( > > > > - > > > > META_MAPPING(F2FS_I_SB(inode)), > > > > - block_nr); > > > > - if (cpage) { > > > > - > > > > f2fs_wait_on_page_writeback(cpage, > > > > - > > > > DATA); > > > > - f2fs_put_page(cpage, 1); > > > > - } > > > > + f2fs_wait_on_encrypted_page_writeback( > > > > + F2FS_I_SB(inode), > > > > block_nr); > > > > } > > > > > > > > bio = bio_alloc(GFP_KERNEL, > > > > @@ -1059,6 +1052,11 @@ int do_write_data_page(struct f2fs_io_info *fio) > > > > } > > > > > > > > if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) { > > > > + > > > > + /* wait for GCed encrypted page writeback */ > > > > + f2fs_wait_on_encrypted_page_writeback(F2FS_I_SB(inode), > > > > + fio->blk_addr); > > > > + > > > > fio->encrypted_page = f2fs_encrypt(inode, fio->page); > > > > if (IS_ERR(fio->encrypted_page)) { > > > > err = PTR_ERR(fio->encrypted_page); > > > > @@ -1446,6 +1444,10 @@ put_next: > > > > > > > > f2fs_wait_on_page_writeback(page, DATA); > > > > > > > > + /* wait for GCed encrypted page writeback */ > > > > + if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) > > > > + f2fs_wait_on_encrypted_page_writeback(sbi, > > > > dn.data_blkaddr); > > > > + > > > > if (len == PAGE_CACHE_SIZE) > > > > goto out_update; > > > > if (PageUptodate(page)) > > > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > > > > index a7522a4..dc4d30b 100644 > > > > --- a/fs/f2fs/f2fs.h > > > > +++ b/fs/f2fs/f2fs.h > > > > @@ -1778,6 +1778,7 @@ void f2fs_replace_block(struct f2fs_sb_info *, > > > > struct dnode_of_data > > > *, > > > > void allocate_data_block(struct f2fs_sb_info *, struct page *, > > > > block_t, block_t *, struct f2fs_summary *, int); > > > > void f2fs_wait_on_page_writeback(struct page *, enum page_type); > > > > +void f2fs_wait_on_encrypted_page_writeback(struct f2fs_sb_info *, > > > > block_t); > > > > void write_data_summaries(struct f2fs_sb_info *, block_t); > > > > void write_node_summaries(struct f2fs_sb_info *, block_t); > > > > int lookup_journal_in_cursum(struct f2fs_summary_block *, > > > > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c > > > > index e2d9910..1d2df88 100644 > > > > --- a/fs/f2fs/file.c > > > > +++ b/fs/f2fs/file.c > > > > @@ -87,6 +87,11 @@ static int f2fs_vm_page_mkwrite(struct > > > > vm_area_struct *vma, > > > > mapped: > > > > /* fill the page */ > > > > f2fs_wait_on_page_writeback(page, DATA); > > > > + > > > > + /* wait for GCed encrypted page writeback */ > > > > + if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) > > > > + f2fs_wait_on_encrypted_page_writeback(sbi, > > > > dn.data_blkaddr); > > > > + > > > > /* if gced page is attached, don't write to cold segment */ > > > > clear_cold_data(page); > > > > out: > > > > diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c > > > > index e7cec86..2493fd6 100644 > > > > --- a/fs/f2fs/gc.c > > > > +++ b/fs/f2fs/gc.c > > > > @@ -559,14 +559,21 @@ static void move_encrypted_block(struct inode > > > > *inode, block_t bidx) > > > > if (err) > > > > goto out; > > > > > > > > - if (unlikely(dn.data_blkaddr == NULL_ADDR)) > > > > + if (unlikely(dn.data_blkaddr == NULL_ADDR)) { > > > > + ClearPageUptodate(page); > > > > goto put_out; > > > > + } > > > > + > > > > + /* > > > > + * don't cache encrypted data into meta inode until previous > > > > dirty > > > > + * data were writebacked to avoid racing between GC and flush. > > > > + */ > > > > + f2fs_wait_on_page_writeback(page, DATA); > > > > > > > > get_node_info(fio.sbi, dn.nid, &ni); > > > > set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version); > > > > > > > > /* read page */ > > > > - fio.page = page; > > > > > > Let's remain just to make sure. > > > > OK. > > > > > > > > > fio.blk_addr = dn.data_blkaddr; > > > > > > > > fio.encrypted_page = pagecache_get_page(META_MAPPING(fio.sbi), > > > > @@ -589,7 +596,7 @@ static void move_encrypted_block(struct inode > > > > *inode, block_t bidx) > > > > goto put_page_out; > > > > > > > > set_page_dirty(fio.encrypted_page); > > > > - f2fs_wait_on_page_writeback(fio.encrypted_page, META); > > > > + f2fs_wait_on_page_writeback(fio.encrypted_page, DATA); > > > > > > Why DATA? > > > > This is because we only submit the encrypted page in to DATA type bio > > cache, so we should check whether the page is cached or not in DATA > > type bio, rather than META type cache. Right? > > Oh, right, type was DATA. :) > I'll test this patch with adding the above initialization.
OK, thanks :) Thanks, > > Thanks, > > > > > Thanks, > > > > > > > > > if (clear_page_dirty_for_io(fio.encrypted_page)) > > > > dec_page_count(fio.sbi, F2FS_DIRTY_META); > > > > > > > > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c > > > > index 3c546eb..d5d760c 100644 > > > > --- a/fs/f2fs/segment.c > > > > +++ b/fs/f2fs/segment.c > > > > @@ -1462,6 +1462,23 @@ void f2fs_wait_on_page_writeback(struct page > > > > *page, > > > > } > > > > } > > > > > > > > +void f2fs_wait_on_encrypted_page_writeback(struct f2fs_sb_info *sbi, > > > > + block_t blkaddr) > > > > +{ > > > > + struct page *cpage; > > > > + > > > > + if (blkaddr == NEW_ADDR) > > > > + return; > > > > + > > > > + f2fs_bug_on(sbi, blkaddr == NULL_ADDR); > > > > + > > > > + cpage = find_lock_page(META_MAPPING(sbi), blkaddr); > > > > + if (cpage) { > > > > + f2fs_wait_on_page_writeback(cpage, DATA); > > > > + f2fs_put_page(cpage, 1); > > > > + } > > > > +} > > > > + > > > > static int read_compacted_summaries(struct f2fs_sb_info *sbi) > > > > { > > > > struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); > > > > -- > > > > 2.5.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/