Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71e9fec5 authored by Jaegeuk Kim's avatar Jaegeuk Kim
Browse files

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: default avatarJaegeuk Kim <jaegeuk.kim@samsung.com>
parent 690e4a3e
Loading
Loading
Loading
Loading
+12 −17
Original line number Diff line number Diff line
@@ -484,12 +484,14 @@ static void truncate_node(struct dnode_of_data *dn)
	struct node_info ni;

	get_node_info(sbi, dn->nid, &ni);
	if (dn->inode->i_blocks == 0) {
		BUG_ON(ni.blk_addr != NULL_ADDR);
		goto invalidate;
	}
	BUG_ON(ni.blk_addr == NULL_ADDR);

	if (ni.blk_addr != NULL_ADDR)
		invalidate_blocks(sbi, ni.blk_addr);

	/* Deallocate node address */
	invalidate_blocks(sbi, ni.blk_addr);
	dec_valid_node_count(sbi, dn->inode, 1);
	set_node_addr(sbi, &ni, NULL_ADDR);

@@ -499,7 +501,7 @@ static void truncate_node(struct dnode_of_data *dn)
	} else {
		sync_inode_page(dn);
	}

invalidate:
	clear_node_page_dirty(dn->node_page);
	F2FS_SET_SB_DIRT(sbi);

@@ -768,20 +770,12 @@ int remove_inode_page(struct inode *inode)
		dn.inode_page_locked = 1;
		truncate_node(&dn);
	}
	if (inode->i_blocks == 1) {
		/* inernally call f2fs_put_page() */

	/* 0 is possible, after f2fs_new_inode() is failed */
	BUG_ON(inode->i_blocks != 0 && inode->i_blocks != 1);
	set_new_dnode(&dn, inode, page, page, ino);
	truncate_node(&dn);
	} else if (inode->i_blocks == 0) {
		struct node_info ni;
		get_node_info(sbi, inode->i_ino, &ni);

		/* called after f2fs_new_inode() is failed */
		BUG_ON(ni.blk_addr != NULL_ADDR);
		f2fs_put_page(page, 1);
	} else {
		BUG();
	}
	mutex_unlock_op(sbi, NODE_TRUNC);
	return 0;
}
@@ -845,6 +839,7 @@ struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs)
	return page;

fail:
	clear_node_page_dirty(page);
	f2fs_put_page(page, 1);
	return ERR_PTR(err);
}