Skip to content

Commit 71e9fec

Browse files
author
Jaegeuk Kim
committed
f2fs: invalidate the node page if allocation is failed
The new_node_page() is processed as the following procedure. 1. A new node page is allocated. 2. Set PageUptodate with proper footer information. 3. Check if there is a free space for allocation 4.a. If there is no space, f2fs returns with -ENOSPC. 4.b. Otherwise, go next. In the case of step #4.a, f2fs remains a wrong node page in the page cache with the uptodate flag. Also, even though a new node page is allocated successfully, an error can be occurred afterwards due to allocation failure of the other data structures. In such a case, remove_inode_page() would be triggered, so that we have to clear uptodate flag in truncate_node() too. So, we should remove the uptodate flag, if allocation is failed. Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent 690e4a3 commit 71e9fec

File tree

1 file changed

+12
-17
lines changed

1 file changed

+12
-17
lines changed

fs/f2fs/node.c

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -484,12 +484,14 @@ static void truncate_node(struct dnode_of_data *dn)
484484
struct node_info ni;
485485

486486
get_node_info(sbi, dn->nid, &ni);
487+
if (dn->inode->i_blocks == 0) {
488+
BUG_ON(ni.blk_addr != NULL_ADDR);
489+
goto invalidate;
490+
}
487491
BUG_ON(ni.blk_addr == NULL_ADDR);
488492

489-
if (ni.blk_addr != NULL_ADDR)
490-
invalidate_blocks(sbi, ni.blk_addr);
491-
492493
/* Deallocate node address */
494+
invalidate_blocks(sbi, ni.blk_addr);
493495
dec_valid_node_count(sbi, dn->inode, 1);
494496
set_node_addr(sbi, &ni, NULL_ADDR);
495497

@@ -499,7 +501,7 @@ static void truncate_node(struct dnode_of_data *dn)
499501
} else {
500502
sync_inode_page(dn);
501503
}
502-
504+
invalidate:
503505
clear_node_page_dirty(dn->node_page);
504506
F2FS_SET_SB_DIRT(sbi);
505507

@@ -768,20 +770,12 @@ int remove_inode_page(struct inode *inode)
768770
dn.inode_page_locked = 1;
769771
truncate_node(&dn);
770772
}
771-
if (inode->i_blocks == 1) {
772-
/* inernally call f2fs_put_page() */
773-
set_new_dnode(&dn, inode, page, page, ino);
774-
truncate_node(&dn);
775-
} else if (inode->i_blocks == 0) {
776-
struct node_info ni;
777-
get_node_info(sbi, inode->i_ino, &ni);
778773

779-
/* called after f2fs_new_inode() is failed */
780-
BUG_ON(ni.blk_addr != NULL_ADDR);
781-
f2fs_put_page(page, 1);
782-
} else {
783-
BUG();
784-
}
774+
/* 0 is possible, after f2fs_new_inode() is failed */
775+
BUG_ON(inode->i_blocks != 0 && inode->i_blocks != 1);
776+
set_new_dnode(&dn, inode, page, page, ino);
777+
truncate_node(&dn);
778+
785779
mutex_unlock_op(sbi, NODE_TRUNC);
786780
return 0;
787781
}
@@ -845,6 +839,7 @@ struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs)
845839
return page;
846840

847841
fail:
842+
clear_node_page_dirty(page);
848843
f2fs_put_page(page, 1);
849844
return ERR_PTR(err);
850845
}

0 commit comments

Comments
 (0)