f2fs: fix stale nids in an indirect node block
Subsystems (2)
Jaegeuk Kim
maintainerPATCH 1/1 f2fs: fix stale nids in an indirect node block
In truncate_inode_blocks, we can get some stale node block addresses in the following scenario.
1. ipage = get_node_page(ino)
2. unlock_page(ipage)
3. trundate_dnode()
- invalidates all the data indices
- truncate node block
4. lock_page(ipage) and then failed, goto restart
5. -ENOMEM or -EIO between #1 and #3
In this case, we already invalidate node block, but its indirect block still has its nid.
Signed-off-by Jaegeuk Kim <[email protected]>
--- fs/f2fs/node.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-)
fs/f2fs/node.c +3 -9
@@ -832,7 +832,7 @@ int truncate_inode_blocks(struct inode *inode, pgoff_t from)trace_f2fs_truncate_inode_blocks_enter (inode, from); level =get_node_path (inode, from, offset, noffset); -restart: + page =get_node_page (sbi, inode->i_ino);if (IS_ERR (page)) {trace_f2fs_truncate_inode_blocks_exit (inode,PTR_ERR (page));
@@ -840,7 +840,7 @@ restart: }set_new_dnode (&dn, inode, page,NULL ,0 ); -unlock_page (page); + dn.inode_page_locked = true; ri =F2FS_INODE (page);switch (level) {
@@ -895,22 +895,16 @@ skip_partial: goto fail;if (offset[1 ] ==0 && ri->i_nid[offset[0 ] -NODE_DIR1_BLOCK ]) { -lock_page (page); -if (unlikely (page->mapping !=NODE_MAPPING (sbi))) { -f2fs_put_page (page,1 ); - goto restart; - }f2fs_wait_on_page_writeback (page,NODE , true); ri->i_nid[offset[0 ] -NODE_DIR1_BLOCK ] =0 ;set_page_dirty (page); -unlock_page (page); } offset[1 ] =0 ; offset[0 ]++; nofs += err; } fail: -f2fs_put_page (page,0 ); +f2fs_put_page (page,1 );trace_f2fs_truncate_inode_blocks_exit (inode, err);return err >0 ?0 : err; }
Signature · 1 line
2.6.3