aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/f2fs/f2fs.h4
-rw-r--r--fs/f2fs/recovery.c43
2 files changed, 22 insertions, 25 deletions
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index dbe5f939b7e7..3b70b0137191 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -137,7 +137,9 @@ struct discard_entry {
137struct fsync_inode_entry { 137struct fsync_inode_entry {
138 struct list_head list; /* list head */ 138 struct list_head list; /* list head */
139 struct inode *inode; /* vfs inode pointer */ 139 struct inode *inode; /* vfs inode pointer */
140 block_t blkaddr; /* block address locating the last inode */ 140 block_t blkaddr; /* block address locating the last fsync */
141 block_t last_dentry; /* block address locating the last dentry */
142 block_t last_inode; /* block address locating the last inode */
141}; 143};
142 144
143#define nats_in_cursum(sum) (le16_to_cpu(sum->n_nats)) 145#define nats_in_cursum(sum) (le16_to_cpu(sum->n_nats))
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 39832833c02f..39c4ff69990e 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -67,7 +67,7 @@ static struct fsync_inode_entry *get_fsync_inode(struct list_head *head,
67 return NULL; 67 return NULL;
68} 68}
69 69
70static int recover_dentry(struct page *ipage, struct inode *inode) 70static int recover_dentry(struct inode *inode, struct page *ipage)
71{ 71{
72 struct f2fs_inode *raw_inode = F2FS_INODE(ipage); 72 struct f2fs_inode *raw_inode = F2FS_INODE(ipage);
73 nid_t pino = le32_to_cpu(raw_inode->i_pino); 73 nid_t pino = le32_to_cpu(raw_inode->i_pino);
@@ -141,7 +141,7 @@ out:
141 return err; 141 return err;
142} 142}
143 143
144static void __recover_inode(struct inode *inode, struct page *page) 144static void recover_inode(struct inode *inode, struct page *page)
145{ 145{
146 struct f2fs_inode *raw = F2FS_INODE(page); 146 struct f2fs_inode *raw = F2FS_INODE(page);
147 147
@@ -153,21 +153,9 @@ static void __recover_inode(struct inode *inode, struct page *page)
153 inode->i_atime.tv_nsec = le32_to_cpu(raw->i_mtime_nsec); 153 inode->i_atime.tv_nsec = le32_to_cpu(raw->i_mtime_nsec);
154 inode->i_ctime.tv_nsec = le32_to_cpu(raw->i_ctime_nsec); 154 inode->i_ctime.tv_nsec = le32_to_cpu(raw->i_ctime_nsec);
155 inode->i_mtime.tv_nsec = le32_to_cpu(raw->i_mtime_nsec); 155 inode->i_mtime.tv_nsec = le32_to_cpu(raw->i_mtime_nsec);
156}
157
158static int recover_inode(struct inode *inode, struct page *node_page)
159{
160 if (!IS_INODE(node_page))
161 return 0;
162
163 __recover_inode(inode, node_page);
164
165 if (is_dent_dnode(node_page))
166 return recover_dentry(node_page, inode);
167 156
168 f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode: ino = %x, name = %s", 157 f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode: ino = %x, name = %s",
169 ino_of_node(node_page), F2FS_INODE(node_page)->i_name); 158 ino_of_node(page), F2FS_INODE(page)->i_name);
170 return 0;
171} 159}
172 160
173static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) 161static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
@@ -210,12 +198,11 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
210 } 198 }
211 199
212 /* add this fsync inode to the list */ 200 /* add this fsync inode to the list */
213 entry = kmem_cache_alloc(fsync_entry_slab, GFP_NOFS); 201 entry = kmem_cache_alloc(fsync_entry_slab, GFP_F2FS_ZERO);
214 if (!entry) { 202 if (!entry) {
215 err = -ENOMEM; 203 err = -ENOMEM;
216 break; 204 break;
217 } 205 }
218
219 /* 206 /*
220 * CP | dnode(F) | inode(DF) 207 * CP | dnode(F) | inode(DF)
221 * For this case, we should not give up now. 208 * For this case, we should not give up now.
@@ -232,9 +219,11 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
232 } 219 }
233 entry->blkaddr = blkaddr; 220 entry->blkaddr = blkaddr;
234 221
235 err = recover_inode(entry->inode, page); 222 if (IS_INODE(page)) {
236 if (err && err != -ENOENT) 223 entry->last_inode = blkaddr;
237 break; 224 if (is_dent_dnode(page))
225 entry->last_dentry = blkaddr;
226 }
238next: 227next:
239 /* check next segment */ 228 /* check next segment */
240 blkaddr = next_blkaddr_of_node(page); 229 blkaddr = next_blkaddr_of_node(page);
@@ -462,11 +451,17 @@ static int recover_data(struct f2fs_sb_info *sbi,
462 /* 451 /*
463 * inode(x) | CP | inode(x) | dnode(F) 452 * inode(x) | CP | inode(x) | dnode(F)
464 * In this case, we can lose the latest inode(x). 453 * In this case, we can lose the latest inode(x).
465 * So, call __recover_inode for the inode update. 454 * So, call recover_inode for the inode update.
466 */ 455 */
467 if (IS_INODE(page)) 456 if (entry->last_inode == blkaddr)
468 __recover_inode(entry->inode, page); 457 recover_inode(entry->inode, page);
469 458 if (entry->last_dentry == blkaddr) {
459 err = recover_dentry(entry->inode, page);
460 if (err) {
461 f2fs_put_page(page, 1);
462 break;
463 }
464 }
470 err = do_recover_data(sbi, entry->inode, page, blkaddr); 465 err = do_recover_data(sbi, entry->inode, page, blkaddr);
471 if (err) { 466 if (err) {
472 f2fs_put_page(page, 1); 467 f2fs_put_page(page, 1);