summaryrefslogtreecommitdiffstats
path: root/fs/f2fs/recovery.c
diff options
context:
space:
mode:
authorJaegeuk Kim2016-09-10 01:59:39 +0200
committerJaegeuk Kim2016-09-13 22:02:29 +0200
commite8ea9b3d7e278d2ef4b60e703f780ceee70cb331 (patch)
tree2ec0fd1ad038bb20032706ed8bc66552d5df9fdb /fs/f2fs/recovery.c
parentf2fs: add common iget in add_fsync_inode (diff)
downloadkernel-qcow2-linux-e8ea9b3d7e278d2ef4b60e703f780ceee70cb331.tar.gz
kernel-qcow2-linux-e8ea9b3d7e278d2ef4b60e703f780ceee70cb331.tar.xz
kernel-qcow2-linux-e8ea9b3d7e278d2ef4b60e703f780ceee70cb331.zip
f2fs: avoid ENOMEM during roll-forward recovery
This patch gives another chances during roll-forward recovery regarding to -ENOMEM. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs/recovery.c')
-rw-r--r--fs/f2fs/recovery.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 1269277773f5..ad748e52956a 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -71,18 +71,14 @@ static struct fsync_inode_entry *get_fsync_inode(struct list_head *head,
static struct fsync_inode_entry *add_fsync_inode(struct f2fs_sb_info *sbi,
struct list_head *head, nid_t ino)
{
- struct inode *inode = f2fs_iget(sbi->sb, ino);
+ struct inode *inode;
struct fsync_inode_entry *entry;
+ inode = f2fs_iget_retry(sbi->sb, ino);
if (IS_ERR(inode))
return ERR_CAST(inode);
- entry = kmem_cache_alloc(fsync_entry_slab, GFP_F2FS_ZERO);
- if (!entry) {
- iput(inode);
- return ERR_PTR(-ENOMEM);
- }
-
+ entry = f2fs_kmem_cache_alloc(fsync_entry_slab, GFP_F2FS_ZERO);
entry->inode = inode;
list_add_tail(&entry->list, head);
@@ -136,7 +132,7 @@ retry:
goto out_unmap_put;
if (de) {
- einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino));
+ einode = f2fs_iget_retry(inode->i_sb, le32_to_cpu(de->ino));
if (IS_ERR(einode)) {
WARN_ON(1);
err = PTR_ERR(einode);
@@ -158,6 +154,8 @@ retry:
err = __f2fs_do_add_link(dir, &fname, inode,
inode->i_ino, inode->i_mode);
}
+ if (err == -ENOMEM)
+ goto retry;
goto out;
out_unmap_put:
@@ -357,7 +355,7 @@ got_it:
if (ino != dn->inode->i_ino) {
/* Deallocate previous index in the node page */
- inode = f2fs_iget(sbi->sb, ino);
+ inode = f2fs_iget_retry(sbi->sb, ino);
if (IS_ERR(inode))
return PTR_ERR(inode);
} else {
@@ -425,10 +423,15 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
end = start + ADDRS_PER_PAGE(page, inode);
set_new_dnode(&dn, inode, NULL, NULL, 0);
-
+retry_dn:
err = get_dnode_of_data(&dn, start, ALLOC_NODE);
- if (err)
+ if (err) {
+ if (err == -ENOMEM) {
+ congestion_wait(BLK_RW_ASYNC, HZ/50);
+ goto retry_dn;
+ }
goto out;
+ }
f2fs_wait_on_page_writeback(dn.node_page, NODE, true);
@@ -479,11 +482,16 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
if (err)
goto err;
}
-
+retry_prev:
/* Check the previous node page having this index */
err = check_index_in_prev_nodes(sbi, dest, &dn);
- if (err)
+ if (err) {
+ if (err == -ENOMEM) {
+ congestion_wait(BLK_RW_ASYNC, HZ/50);
+ goto retry_prev;
+ }
goto err;
+ }
/* write dummy data page */
f2fs_replace_block(sbi, &dn, src, dest,