f2fs: fix deadlock during inline_data conversion
Subsystems (2)
Jaegeuk Kim
maintainerPATCH 1/2 f2fs: fix deadlock during inline_data conversion
A deadlock can be occurred:
Thread 1] Thread 2]
- f2fs_write_data_pages - f2fs_write_begin
- lock_page(page #0)
- grab_cache_page(page #X)
- get_node_page(inode_page)
- grab_cache_page(page #0) : to convert inline_data
- f2fs_write_data_page
- f2fs_write_inline_data
- get_node_page(inode_page)
In this case, trying to lock inode_page and page #0 causes deadlock. In order to avoid this, this patch adds a rule for this locking policy, which is that page #0 should be locked followed by inode_page lock.
--- fs/f2fs/data.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-)
fs/f2fs/data.c +14 -14
@@ -936,6 +936,17 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,trace_f2fs_write_begin (inode, pos, len, flags);f2fs_balance_fs (sbi); + +/* +* We should check this at this moment to avoid deadlock on inode page +* and #0 page. The locking rule for inline_data conversion should be: +* lock_page(page #0) -> lock_page(inode_page) +*/ +if (index !=0 ) { + err =f2fs_convert_inline_inode (inode); +if (err) + goto fail; + } repeat: page =grab_cache_page_write_begin (mapping, index, flags);if (!page) {
@@ -960,21 +971,10 @@ repeat:set_inode_flag (F2FS_I (inode),FI_DATA_EXIST );sync_inode_page (&dn); goto put_next; - }else if (page->index ==0 ) { - err =f2fs_convert_inline_page (&dn, page); -if (err) - goto put_fail; - }else { -struct page *p =grab_cache_page (inode->i_mapping,0 ); -if (!p) { - err = -ENOMEM ; - goto put_fail; - } - err =f2fs_convert_inline_page (&dn, p); -f2fs_put_page (p,1 ); -if (err) - goto put_fail; } + err =f2fs_convert_inline_page (&dn, page); +if (err) + goto put_fail; } err =f2fs_reserve_block (&dn, index);if (err)
Signature · 9 lines
2.1.1 ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=157005751&iu=/4140/ostg.clktrk
Jaegeuk Kim
maintainerPATCH 2/2 f2fs: make clean the page before writing
If a page is set to be written to the disk, we can make clean the page.
--- fs/f2fs/inline.c | 3 +++ 1 file changed, 3 insertions(+)
fs/f2fs/inline.c +3 -0
@@ -110,6 +110,9 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)kunmap_atomic (dst_addr);SetPageUptodate (page); no_update: +/* clear dirty state */ +clear_page_dirty_for_io (page); +/* write data page to try to make data consistent */ set_page_writeback (page);
Signature · 1 line
2.1.1
Jaegeuk Kim
maintainerPATCH v2 2/2 f2fs: make clean the page before writing
Change log from v1:
o fix to handle # of dirty pages
If a page is set to be written to the disk, we can make clean the page.
--- fs/f2fs/inline.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
fs/f2fs/inline.c +6 -1
@@ -84,7 +84,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page) .type = DATA, .rw = WRITE_SYNC | REQ_PRIO, }; -int err; +int dirty, err;f2fs_bug_on (F2FS_I_SB (dn->inode), page->index);
@@ -110,12 +110,17 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)kunmap_atomic (dst_addr);SetPageUptodate (page); no_update: +/* clear dirty state */ + dirty =clear_page_dirty_for_io (page); +/* write data page to try to make data consistent */ set_page_writeback (page);write_data_page (page, dn, &new_blk_addr, &fio);update_extent_cache (new_blk_addr, dn);f2fs_wait_on_page_writeback (page,DATA ); +if (dirty) +inode_dec_dirty_pages (dn->inode);/* clear inline data and flag after data writeback */ truncate_inline_data (dn->inode_page,0 );
Signature · 1 line
2.1.1