aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/f2fs/checkpoint.c23
-rw-r--r--fs/f2fs/f2fs.h2
-rw-r--r--fs/f2fs/recovery.c14
3 files changed, 34 insertions, 5 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index b1de01da1a40..3d1144908ac6 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -514,6 +514,29 @@ void remove_dirty_dir_inode(struct inode *inode)
514 } 514 }
515out: 515out:
516 spin_unlock(&sbi->dir_inode_lock); 516 spin_unlock(&sbi->dir_inode_lock);
517
518 /* Only from the recovery routine */
519 if (is_inode_flag_set(F2FS_I(inode), FI_DELAY_IPUT))
520 iput(inode);
521}
522
523struct inode *check_dirty_dir_inode(struct f2fs_sb_info *sbi, nid_t ino)
524{
525 struct list_head *head = &sbi->dir_inode_list;
526 struct list_head *this;
527 struct inode *inode = NULL;
528
529 spin_lock(&sbi->dir_inode_lock);
530 list_for_each(this, head) {
531 struct dir_inode_entry *entry;
532 entry = list_entry(this, struct dir_inode_entry, list);
533 if (entry->inode->i_ino == ino) {
534 inode = entry->inode;
535 break;
536 }
537 }
538 spin_unlock(&sbi->dir_inode_lock);
539 return inode;
517} 540}
518 541
519void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi) 542void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 20aab02f2a42..ef6cac8c16a5 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -846,6 +846,7 @@ enum {
846 FI_INC_LINK, /* need to increment i_nlink */ 846 FI_INC_LINK, /* need to increment i_nlink */
847 FI_ACL_MODE, /* indicate acl mode */ 847 FI_ACL_MODE, /* indicate acl mode */
848 FI_NO_ALLOC, /* should not allocate any blocks */ 848 FI_NO_ALLOC, /* should not allocate any blocks */
849 FI_DELAY_IPUT, /* used for the recovery */
849}; 850};
850 851
851static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag) 852static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
@@ -1012,6 +1013,7 @@ int recover_orphan_inodes(struct f2fs_sb_info *);
1012int get_valid_checkpoint(struct f2fs_sb_info *); 1013int get_valid_checkpoint(struct f2fs_sb_info *);
1013void set_dirty_dir_page(struct inode *, struct page *); 1014void set_dirty_dir_page(struct inode *, struct page *);
1014void remove_dirty_dir_inode(struct inode *); 1015void remove_dirty_dir_inode(struct inode *);
1016struct inode *check_dirty_dir_inode(struct f2fs_sb_info *, nid_t);
1015void sync_dirty_dir_inodes(struct f2fs_sb_info *); 1017void sync_dirty_dir_inodes(struct f2fs_sb_info *);
1016void write_checkpoint(struct f2fs_sb_info *, bool); 1018void write_checkpoint(struct f2fs_sb_info *, bool);
1017void init_orphan_info(struct f2fs_sb_info *); 1019void init_orphan_info(struct f2fs_sb_info *);
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 4d895149a6f0..23f580397e6c 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -42,6 +42,7 @@ static int recover_dentry(struct page *ipage, struct inode *inode)
42{ 42{
43 struct f2fs_node *raw_node = (struct f2fs_node *)kmap(ipage); 43 struct f2fs_node *raw_node = (struct f2fs_node *)kmap(ipage);
44 struct f2fs_inode *raw_inode = &(raw_node->i); 44 struct f2fs_inode *raw_inode = &(raw_node->i);
45 nid_t pino = le32_to_cpu(raw_inode->i_pino);
45 struct qstr name; 46 struct qstr name;
46 struct f2fs_dir_entry *de; 47 struct f2fs_dir_entry *de;
47 struct page *page; 48 struct page *page;
@@ -51,10 +52,14 @@ static int recover_dentry(struct page *ipage, struct inode *inode)
51 if (!is_dent_dnode(ipage)) 52 if (!is_dent_dnode(ipage))
52 goto out; 53 goto out;
53 54
54 dir = f2fs_iget(inode->i_sb, le32_to_cpu(raw_inode->i_pino)); 55 dir = check_dirty_dir_inode(F2FS_SB(inode->i_sb), pino);
55 if (IS_ERR(dir)) { 56 if (!dir) {
56 err = PTR_ERR(dir); 57 dir = f2fs_iget(inode->i_sb, pino);
57 goto out; 58 if (IS_ERR(dir)) {
59 err = PTR_ERR(dir);
60 goto out;
61 }
62 set_inode_flag(F2FS_I(dir), FI_DELAY_IPUT);
58 } 63 }
59 64
60 name.len = le32_to_cpu(raw_inode->i_namelen); 65 name.len = le32_to_cpu(raw_inode->i_namelen);
@@ -67,7 +72,6 @@ static int recover_dentry(struct page *ipage, struct inode *inode)
67 } else { 72 } else {
68 err = __f2fs_add_link(dir, &name, inode); 73 err = __f2fs_add_link(dir, &name, inode);
69 } 74 }
70 iput(dir);
71out: 75out:
72 kunmap(ipage); 76 kunmap(ipage);
73 return err; 77 return err;