f2fs: call f2fs_wait_on_page_writeback instead of native function
If a page is on writeback, f2fs can face with deadlock due to under writepages. This is caused by merging IOs inside f2fs, so if it comes to detect, let's throw merged IOs, which is implemented by f2fs_wait_on_page_writeback. Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
This commit is contained in:
parent
50c8cdb35a
commit
3cb5ad152b
5 changed files with 16 additions and 19 deletions
|
@ -33,14 +33,12 @@ struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
|
|||
struct address_space *mapping = META_MAPPING(sbi);
|
||||
struct page *page = NULL;
|
||||
repeat:
|
||||
page = grab_cache_page(mapping, index);
|
||||
page = grab_cache_page_write_begin(mapping, index, AOP_FLAG_NOFS);
|
||||
if (!page) {
|
||||
cond_resched();
|
||||
goto repeat;
|
||||
}
|
||||
|
||||
/* We wait writeback only inside grab_meta_page() */
|
||||
wait_on_page_writeback(page);
|
||||
SetPageUptodate(page);
|
||||
return page;
|
||||
}
|
||||
|
@ -168,7 +166,7 @@ static int f2fs_write_meta_page(struct page *page,
|
|||
if (unlikely(is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)))
|
||||
goto no_write;
|
||||
|
||||
wait_on_page_writeback(page);
|
||||
f2fs_wait_on_page_writeback(page, META);
|
||||
write_meta_page(sbi, page);
|
||||
no_write:
|
||||
dec_page_count(sbi, F2FS_DIRTY_META);
|
||||
|
|
|
@ -253,7 +253,7 @@ void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
|
|||
struct page *page, struct inode *inode)
|
||||
{
|
||||
lock_page(page);
|
||||
wait_on_page_writeback(page);
|
||||
f2fs_wait_on_page_writeback(page, DATA);
|
||||
de->ino = cpu_to_le32(inode->i_ino);
|
||||
set_de_type(de, inode);
|
||||
kunmap(page);
|
||||
|
@ -352,14 +352,11 @@ static struct page *init_inode_metadata(struct inode *inode,
|
|||
err = f2fs_init_security(inode, dir, name, page);
|
||||
if (err)
|
||||
goto put_error;
|
||||
|
||||
wait_on_page_writeback(page);
|
||||
} else {
|
||||
page = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino);
|
||||
if (IS_ERR(page))
|
||||
return page;
|
||||
|
||||
wait_on_page_writeback(page);
|
||||
set_cold_node(inode, page);
|
||||
}
|
||||
|
||||
|
@ -494,7 +491,7 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name,
|
|||
++level;
|
||||
goto start;
|
||||
add_dentry:
|
||||
wait_on_page_writeback(dentry_page);
|
||||
f2fs_wait_on_page_writeback(dentry_page, DATA);
|
||||
|
||||
page = init_inode_metadata(inode, dir, name);
|
||||
if (IS_ERR(page)) {
|
||||
|
@ -543,7 +540,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
|
|||
int i;
|
||||
|
||||
lock_page(page);
|
||||
wait_on_page_writeback(page);
|
||||
f2fs_wait_on_page_writeback(page, DATA);
|
||||
|
||||
dentry_blk = (struct f2fs_dentry_block *)kaddr;
|
||||
bit_pos = dentry - (struct f2fs_dir_entry *)dentry_blk->dentry;
|
||||
|
|
|
@ -76,7 +76,7 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
|
|||
trace_f2fs_vm_page_mkwrite(page, DATA);
|
||||
mapped:
|
||||
/* fill the page */
|
||||
wait_on_page_writeback(page);
|
||||
f2fs_wait_on_page_writeback(page, DATA);
|
||||
out:
|
||||
sb_end_pagefault(inode->i_sb);
|
||||
return block_page_mkwrite_return(err);
|
||||
|
@ -245,7 +245,7 @@ static void truncate_partial_data_page(struct inode *inode, u64 from)
|
|||
f2fs_put_page(page, 1);
|
||||
return;
|
||||
}
|
||||
wait_on_page_writeback(page);
|
||||
f2fs_wait_on_page_writeback(page, DATA);
|
||||
zero_user(page, offset, PAGE_CACHE_SIZE - offset);
|
||||
set_page_dirty(page);
|
||||
f2fs_put_page(page, 1);
|
||||
|
@ -422,7 +422,7 @@ static void fill_zero(struct inode *inode, pgoff_t index,
|
|||
f2fs_unlock_op(sbi);
|
||||
|
||||
if (!IS_ERR(page)) {
|
||||
wait_on_page_writeback(page);
|
||||
f2fs_wait_on_page_writeback(page, DATA);
|
||||
zero_user(page, start, len);
|
||||
set_page_dirty(page);
|
||||
f2fs_put_page(page, 1);
|
||||
|
|
|
@ -725,7 +725,7 @@ int truncate_inode_blocks(struct inode *inode, pgoff_t from)
|
|||
f2fs_put_page(page, 1);
|
||||
goto restart;
|
||||
}
|
||||
wait_on_page_writeback(page);
|
||||
f2fs_wait_on_page_writeback(page, NODE);
|
||||
ri->i_nid[offset[0] - NODE_DIR1_BLOCK] = 0;
|
||||
set_page_dirty(page);
|
||||
unlock_page(page);
|
||||
|
@ -814,7 +814,8 @@ struct page *new_node_page(struct dnode_of_data *dn,
|
|||
if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC)))
|
||||
return ERR_PTR(-EPERM);
|
||||
|
||||
page = grab_cache_page(NODE_MAPPING(sbi), dn->nid);
|
||||
page = grab_cache_page_write_begin(NODE_MAPPING(sbi),
|
||||
dn->nid, AOP_FLAG_NOFS);
|
||||
if (!page)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
@ -910,7 +911,8 @@ struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid)
|
|||
struct page *page;
|
||||
int err;
|
||||
repeat:
|
||||
page = grab_cache_page(NODE_MAPPING(sbi), nid);
|
||||
page = grab_cache_page_write_begin(NODE_MAPPING(sbi),
|
||||
nid, AOP_FLAG_NOFS);
|
||||
if (!page)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
@ -1130,7 +1132,7 @@ int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
|
|||
continue;
|
||||
|
||||
if (ino && ino_of_node(page) == ino) {
|
||||
wait_on_page_writeback(page);
|
||||
f2fs_wait_on_page_writeback(page, NODE);
|
||||
if (TestClearPageError(page))
|
||||
ret = -EIO;
|
||||
}
|
||||
|
@ -1163,7 +1165,7 @@ static int f2fs_write_node_page(struct page *page,
|
|||
if (unlikely(sbi->por_doing))
|
||||
goto redirty_out;
|
||||
|
||||
wait_on_page_writeback(page);
|
||||
f2fs_wait_on_page_writeback(page, NODE);
|
||||
|
||||
/* get old block addr of this node page */
|
||||
nid = nid_of_node(page);
|
||||
|
|
|
@ -316,7 +316,7 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
|
|||
goto out;
|
||||
}
|
||||
|
||||
wait_on_page_writeback(dn.node_page);
|
||||
f2fs_wait_on_page_writeback(dn.node_page, NODE);
|
||||
|
||||
get_node_info(sbi, dn.nid, &ni);
|
||||
f2fs_bug_on(ni.ino != ino_of_node(page));
|
||||
|
|
Loading…
Reference in a new issue