UPSTREAM: f2fs: do not bother checkpoint by f2fs_get_node_info
This patch tries to mitigate lock contention between f2fs_write_checkpoint and f2fs_get_node_info along with nat_tree_lock. The idea is, if checkpoint is currently running, other threads that try to grab nat_tree_lock would be better to wait for checkpoint. Bug: 214413989 Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> (cherry picked from commit a9419b63bf414775e8aeee95d8c4a5e0df690748 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master) Change-Id: I7e253e8bf26012e451330ba6ce00bfc3839bdda3
This commit is contained in:
@@ -650,7 +650,7 @@ static int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
|
|||||||
/* truncate all the data during iput */
|
/* truncate all the data during iput */
|
||||||
iput(inode);
|
iput(inode);
|
||||||
|
|
||||||
err = f2fs_get_node_info(sbi, ino, &ni);
|
err = f2fs_get_node_info(sbi, ino, &ni, false);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
|
@@ -1222,7 +1222,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,
|
|||||||
|
|
||||||
psize = (loff_t)(cc->rpages[last_index]->index + 1) << PAGE_SHIFT;
|
psize = (loff_t)(cc->rpages[last_index]->index + 1) << PAGE_SHIFT;
|
||||||
|
|
||||||
err = f2fs_get_node_info(fio.sbi, dn.nid, &ni);
|
err = f2fs_get_node_info(fio.sbi, dn.nid, &ni, false);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_put_dnode;
|
goto out_put_dnode;
|
||||||
|
|
||||||
|
@@ -1356,7 +1356,7 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
|
|||||||
if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC)))
|
if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC)))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
err = f2fs_get_node_info(sbi, dn->nid, &ni);
|
err = f2fs_get_node_info(sbi, dn->nid, &ni, false);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@@ -1791,7 +1791,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
|
|||||||
if (!page)
|
if (!page)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
err = f2fs_get_node_info(sbi, inode->i_ino, &ni);
|
err = f2fs_get_node_info(sbi, inode->i_ino, &ni, false);
|
||||||
if (err) {
|
if (err) {
|
||||||
f2fs_put_page(page, 1);
|
f2fs_put_page(page, 1);
|
||||||
return err;
|
return err;
|
||||||
@@ -1823,7 +1823,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
|
|||||||
if (!page)
|
if (!page)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
err = f2fs_get_node_info(sbi, xnid, &ni);
|
err = f2fs_get_node_info(sbi, xnid, &ni, false);
|
||||||
if (err) {
|
if (err) {
|
||||||
f2fs_put_page(page, 1);
|
f2fs_put_page(page, 1);
|
||||||
return err;
|
return err;
|
||||||
@@ -2655,7 +2655,7 @@ got_it:
|
|||||||
fio->need_lock = LOCK_REQ;
|
fio->need_lock = LOCK_REQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = f2fs_get_node_info(fio->sbi, dn.nid, &ni);
|
err = f2fs_get_node_info(fio->sbi, dn.nid, &ni, false);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_writepage;
|
goto out_writepage;
|
||||||
|
|
||||||
|
@@ -3410,7 +3410,7 @@ int f2fs_need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid);
|
|||||||
bool f2fs_is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid);
|
bool f2fs_is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid);
|
||||||
bool f2fs_need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino);
|
bool f2fs_need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino);
|
||||||
int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
|
int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
|
||||||
struct node_info *ni);
|
struct node_info *ni, bool checkpoint_context);
|
||||||
pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs);
|
pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs);
|
||||||
int f2fs_get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode);
|
int f2fs_get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode);
|
||||||
int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from);
|
int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from);
|
||||||
|
@@ -1211,7 +1211,7 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = f2fs_get_node_info(sbi, dn.nid, &ni);
|
ret = f2fs_get_node_info(sbi, dn.nid, &ni, false);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
f2fs_put_dnode(&dn);
|
f2fs_put_dnode(&dn);
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -941,7 +941,7 @@ next_step:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f2fs_get_node_info(sbi, nid, &ni)) {
|
if (f2fs_get_node_info(sbi, nid, &ni, false)) {
|
||||||
f2fs_put_page(node_page, 1);
|
f2fs_put_page(node_page, 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1009,7 +1009,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
|
|||||||
if (IS_ERR(node_page))
|
if (IS_ERR(node_page))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (f2fs_get_node_info(sbi, nid, dni)) {
|
if (f2fs_get_node_info(sbi, nid, dni, false)) {
|
||||||
f2fs_put_page(node_page, 1);
|
f2fs_put_page(node_page, 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1200,7 +1200,7 @@ static int move_data_block(struct inode *inode, block_t bidx,
|
|||||||
|
|
||||||
f2fs_wait_on_block_writeback(inode, dn.data_blkaddr);
|
f2fs_wait_on_block_writeback(inode, dn.data_blkaddr);
|
||||||
|
|
||||||
err = f2fs_get_node_info(fio.sbi, dn.nid, &ni);
|
err = f2fs_get_node_info(fio.sbi, dn.nid, &ni, false);
|
||||||
if (err)
|
if (err)
|
||||||
goto put_out;
|
goto put_out;
|
||||||
|
|
||||||
|
@@ -149,7 +149,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = f2fs_get_node_info(fio.sbi, dn->nid, &ni);
|
err = f2fs_get_node_info(fio.sbi, dn->nid, &ni, false);
|
||||||
if (err) {
|
if (err) {
|
||||||
f2fs_truncate_data_blocks_range(dn, 1);
|
f2fs_truncate_data_blocks_range(dn, 1);
|
||||||
f2fs_put_dnode(dn);
|
f2fs_put_dnode(dn);
|
||||||
@@ -804,7 +804,7 @@ int f2fs_inline_data_fiemap(struct inode *inode,
|
|||||||
ilen = start + len;
|
ilen = start + len;
|
||||||
ilen -= start;
|
ilen -= start;
|
||||||
|
|
||||||
err = f2fs_get_node_info(F2FS_I_SB(inode), inode->i_ino, &ni);
|
err = f2fs_get_node_info(F2FS_I_SB(inode), inode->i_ino, &ni, false);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@@ -868,7 +868,7 @@ void f2fs_handle_failed_inode(struct inode *inode)
|
|||||||
* so we can prevent losing this orphan when encoutering checkpoint
|
* so we can prevent losing this orphan when encoutering checkpoint
|
||||||
* and following suddenly power-off.
|
* and following suddenly power-off.
|
||||||
*/
|
*/
|
||||||
err = f2fs_get_node_info(sbi, inode->i_ino, &ni);
|
err = f2fs_get_node_info(sbi, inode->i_ino, &ni, false);
|
||||||
if (err) {
|
if (err) {
|
||||||
set_sbi_flag(sbi, SBI_NEED_FSCK);
|
set_sbi_flag(sbi, SBI_NEED_FSCK);
|
||||||
f2fs_warn(sbi, "May loss orphan inode, run fsck to fix.");
|
f2fs_warn(sbi, "May loss orphan inode, run fsck to fix.");
|
||||||
|
@@ -541,7 +541,7 @@ int f2fs_try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
|
int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
|
||||||
struct node_info *ni)
|
struct node_info *ni, bool checkpoint_context)
|
||||||
{
|
{
|
||||||
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
||||||
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
|
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
|
||||||
@@ -574,9 +574,10 @@ retry:
|
|||||||
* nat_tree_lock. Therefore, we should retry, if we failed to grab here
|
* nat_tree_lock. Therefore, we should retry, if we failed to grab here
|
||||||
* while not bothering checkpoint.
|
* while not bothering checkpoint.
|
||||||
*/
|
*/
|
||||||
if (!rwsem_is_locked(&sbi->cp_global_sem)) {
|
if (!rwsem_is_locked(&sbi->cp_global_sem) || checkpoint_context) {
|
||||||
down_read(&curseg->journal_rwsem);
|
down_read(&curseg->journal_rwsem);
|
||||||
} else if (!down_read_trylock(&curseg->journal_rwsem)) {
|
} else if (rwsem_is_contended(&nm_i->nat_tree_lock) ||
|
||||||
|
!down_read_trylock(&curseg->journal_rwsem)) {
|
||||||
up_read(&nm_i->nat_tree_lock);
|
up_read(&nm_i->nat_tree_lock);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
@@ -869,7 +870,7 @@ static int truncate_node(struct dnode_of_data *dn)
|
|||||||
int err;
|
int err;
|
||||||
pgoff_t index;
|
pgoff_t index;
|
||||||
|
|
||||||
err = f2fs_get_node_info(sbi, dn->nid, &ni);
|
err = f2fs_get_node_info(sbi, dn->nid, &ni, false);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@@ -1268,7 +1269,7 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs)
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
#ifdef CONFIG_F2FS_CHECK_FS
|
#ifdef CONFIG_F2FS_CHECK_FS
|
||||||
err = f2fs_get_node_info(sbi, dn->nid, &new_ni);
|
err = f2fs_get_node_info(sbi, dn->nid, &new_ni, false);
|
||||||
if (err) {
|
if (err) {
|
||||||
dec_valid_node_count(sbi, dn->inode, !ofs);
|
dec_valid_node_count(sbi, dn->inode, !ofs);
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -1330,7 +1331,7 @@ static int read_node_page(struct page *page, int op_flags)
|
|||||||
return LOCKED_PAGE;
|
return LOCKED_PAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = f2fs_get_node_info(sbi, page->index, &ni);
|
err = f2fs_get_node_info(sbi, page->index, &ni, false);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@@ -1583,7 +1584,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
|
|||||||
nid = nid_of_node(page);
|
nid = nid_of_node(page);
|
||||||
f2fs_bug_on(sbi, page->index != nid);
|
f2fs_bug_on(sbi, page->index != nid);
|
||||||
|
|
||||||
if (f2fs_get_node_info(sbi, nid, &ni))
|
if (f2fs_get_node_info(sbi, nid, &ni, !do_balance))
|
||||||
goto redirty_out;
|
goto redirty_out;
|
||||||
|
|
||||||
if (wbc->for_reclaim) {
|
if (wbc->for_reclaim) {
|
||||||
@@ -2666,7 +2667,7 @@ int f2fs_recover_xattr_data(struct inode *inode, struct page *page)
|
|||||||
goto recover_xnid;
|
goto recover_xnid;
|
||||||
|
|
||||||
/* 1: invalidate the previous xattr nid */
|
/* 1: invalidate the previous xattr nid */
|
||||||
err = f2fs_get_node_info(sbi, prev_xnid, &ni);
|
err = f2fs_get_node_info(sbi, prev_xnid, &ni, false);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@@ -2706,7 +2707,7 @@ int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
|
|||||||
struct page *ipage;
|
struct page *ipage;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = f2fs_get_node_info(sbi, ino, &old_ni);
|
err = f2fs_get_node_info(sbi, ino, &old_ni, false);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@@ -594,7 +594,7 @@ retry_dn:
|
|||||||
|
|
||||||
f2fs_wait_on_page_writeback(dn.node_page, NODE, true, true);
|
f2fs_wait_on_page_writeback(dn.node_page, NODE, true, true);
|
||||||
|
|
||||||
err = f2fs_get_node_info(sbi, dn.nid, &ni);
|
err = f2fs_get_node_info(sbi, dn.nid, &ni, false);
|
||||||
if (err)
|
if (err)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@@ -251,7 +251,7 @@ retry:
|
|||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = f2fs_get_node_info(sbi, dn.nid, &ni);
|
err = f2fs_get_node_info(sbi, dn.nid, &ni, false);
|
||||||
if (err) {
|
if (err) {
|
||||||
f2fs_put_dnode(&dn);
|
f2fs_put_dnode(&dn);
|
||||||
return err;
|
return err;
|
||||||
|
Reference in New Issue
Block a user