aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/recovery.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/f2fs/recovery.c')
-rw-r--r--fs/f2fs/recovery.c76
1 files changed, 44 insertions, 32 deletions
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 41afb9534bbd..8d8ea99f2156 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -93,10 +93,9 @@ static int recover_dentry(struct inode *inode, struct page *ipage)
93 } 93 }
94retry: 94retry:
95 de = f2fs_find_entry(dir, &name, &page); 95 de = f2fs_find_entry(dir, &name, &page);
96 if (de && inode->i_ino == le32_to_cpu(de->ino)) { 96 if (de && inode->i_ino == le32_to_cpu(de->ino))
97 clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
98 goto out_unmap_put; 97 goto out_unmap_put;
99 } 98
100 if (de) { 99 if (de) {
101 einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino)); 100 einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino));
102 if (IS_ERR(einode)) { 101 if (IS_ERR(einode)) {
@@ -115,7 +114,7 @@ retry:
115 iput(einode); 114 iput(einode);
116 goto retry; 115 goto retry;
117 } 116 }
118 err = __f2fs_add_link(dir, &name, inode); 117 err = __f2fs_add_link(dir, &name, inode, inode->i_ino, inode->i_mode);
119 if (err) 118 if (err)
120 goto out_err; 119 goto out_err;
121 120
@@ -187,11 +186,7 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
187 goto next; 186 goto next;
188 187
189 entry = get_fsync_inode(head, ino_of_node(page)); 188 entry = get_fsync_inode(head, ino_of_node(page));
190 if (entry) { 189 if (!entry) {
191 if (IS_INODE(page) && is_dent_dnode(page))
192 set_inode_flag(F2FS_I(entry->inode),
193 FI_INC_LINK);
194 } else {
195 if (IS_INODE(page) && is_dent_dnode(page)) { 190 if (IS_INODE(page) && is_dent_dnode(page)) {
196 err = recover_inode_page(sbi, page); 191 err = recover_inode_page(sbi, page);
197 if (err) 192 if (err)
@@ -212,8 +207,10 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
212 if (IS_ERR(entry->inode)) { 207 if (IS_ERR(entry->inode)) {
213 err = PTR_ERR(entry->inode); 208 err = PTR_ERR(entry->inode);
214 kmem_cache_free(fsync_entry_slab, entry); 209 kmem_cache_free(fsync_entry_slab, entry);
215 if (err == -ENOENT) 210 if (err == -ENOENT) {
211 err = 0;
216 goto next; 212 goto next;
213 }
217 break; 214 break;
218 } 215 }
219 list_add_tail(&entry->list, head); 216 list_add_tail(&entry->list, head);
@@ -256,6 +253,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
256 struct f2fs_summary_block *sum_node; 253 struct f2fs_summary_block *sum_node;
257 struct f2fs_summary sum; 254 struct f2fs_summary sum;
258 struct page *sum_page, *node_page; 255 struct page *sum_page, *node_page;
256 struct dnode_of_data tdn = *dn;
259 nid_t ino, nid; 257 nid_t ino, nid;
260 struct inode *inode; 258 struct inode *inode;
261 unsigned int offset; 259 unsigned int offset;
@@ -283,17 +281,15 @@ got_it:
283 /* Use the locked dnode page and inode */ 281 /* Use the locked dnode page and inode */
284 nid = le32_to_cpu(sum.nid); 282 nid = le32_to_cpu(sum.nid);
285 if (dn->inode->i_ino == nid) { 283 if (dn->inode->i_ino == nid) {
286 struct dnode_of_data tdn = *dn;
287 tdn.nid = nid; 284 tdn.nid = nid;
285 if (!dn->inode_page_locked)
286 lock_page(dn->inode_page);
288 tdn.node_page = dn->inode_page; 287 tdn.node_page = dn->inode_page;
289 tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node); 288 tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node);
290 truncate_data_blocks_range(&tdn, 1); 289 goto truncate_out;
291 return 0;
292 } else if (dn->nid == nid) { 290 } else if (dn->nid == nid) {
293 struct dnode_of_data tdn = *dn;
294 tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node); 291 tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node);
295 truncate_data_blocks_range(&tdn, 1); 292 goto truncate_out;
296 return 0;
297 } 293 }
298 294
299 /* Get the node page */ 295 /* Get the node page */
@@ -317,18 +313,33 @@ got_it:
317 bidx = start_bidx_of_node(offset, F2FS_I(inode)) + 313 bidx = start_bidx_of_node(offset, F2FS_I(inode)) +
318 le16_to_cpu(sum.ofs_in_node); 314 le16_to_cpu(sum.ofs_in_node);
319 315
320 if (ino != dn->inode->i_ino) { 316 /*
321 truncate_hole(inode, bidx, bidx + 1); 317 * if inode page is locked, unlock temporarily, but its reference
318 * count keeps alive.
319 */
320 if (ino == dn->inode->i_ino && dn->inode_page_locked)
321 unlock_page(dn->inode_page);
322
323 set_new_dnode(&tdn, inode, NULL, NULL, 0);
324 if (get_dnode_of_data(&tdn, bidx, LOOKUP_NODE))
325 goto out;
326
327 if (tdn.data_blkaddr == blkaddr)
328 truncate_data_blocks_range(&tdn, 1);
329
330 f2fs_put_dnode(&tdn);
331out:
332 if (ino != dn->inode->i_ino)
322 iput(inode); 333 iput(inode);
323 } else { 334 else if (dn->inode_page_locked)
324 struct dnode_of_data tdn; 335 lock_page(dn->inode_page);
325 set_new_dnode(&tdn, inode, dn->inode_page, NULL, 0); 336 return 0;
326 if (get_dnode_of_data(&tdn, bidx, LOOKUP_NODE)) 337
327 return 0; 338truncate_out:
328 if (tdn.data_blkaddr != NULL_ADDR) 339 if (datablock_addr(tdn.node_page, tdn.ofs_in_node) == blkaddr)
329 truncate_data_blocks_range(&tdn, 1); 340 truncate_data_blocks_range(&tdn, 1);
330 f2fs_put_page(tdn.node_page, 1); 341 if (dn->inode->i_ino == nid && !dn->inode_page_locked)
331 } 342 unlock_page(dn->inode_page);
332 return 0; 343 return 0;
333} 344}
334 345
@@ -384,7 +395,9 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
384 src = datablock_addr(dn.node_page, dn.ofs_in_node); 395 src = datablock_addr(dn.node_page, dn.ofs_in_node);
385 dest = datablock_addr(page, dn.ofs_in_node); 396 dest = datablock_addr(page, dn.ofs_in_node);
386 397
387 if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR) { 398 if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR &&
399 dest >= MAIN_BLKADDR(sbi) && dest < MAX_BLKADDR(sbi)) {
400
388 if (src == NULL_ADDR) { 401 if (src == NULL_ADDR) {
389 err = reserve_new_block(&dn); 402 err = reserve_new_block(&dn);
390 /* We should not get -ENOSPC */ 403 /* We should not get -ENOSPC */
@@ -401,14 +414,13 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
401 /* write dummy data page */ 414 /* write dummy data page */
402 recover_data_page(sbi, NULL, &sum, src, dest); 415 recover_data_page(sbi, NULL, &sum, src, dest);
403 dn.data_blkaddr = dest; 416 dn.data_blkaddr = dest;
404 update_extent_cache(&dn); 417 set_data_blkaddr(&dn);
418 f2fs_update_extent_cache(&dn);
405 recovered++; 419 recovered++;
406 } 420 }
407 dn.ofs_in_node++; 421 dn.ofs_in_node++;
408 } 422 }
409 423
410 /* write node page in place */
411 set_summary(&sum, dn.nid, 0, 0);
412 if (IS_INODE(dn.node_page)) 424 if (IS_INODE(dn.node_page))
413 sync_inode_page(&dn); 425 sync_inode_page(&dn);
414 426
@@ -552,7 +564,7 @@ out:
552 mutex_unlock(&sbi->cp_mutex); 564 mutex_unlock(&sbi->cp_mutex);
553 } else if (need_writecp) { 565 } else if (need_writecp) {
554 struct cp_control cpc = { 566 struct cp_control cpc = {
555 .reason = CP_SYNC, 567 .reason = CP_RECOVERY,
556 }; 568 };
557 mutex_unlock(&sbi->cp_mutex); 569 mutex_unlock(&sbi->cp_mutex);
558 write_checkpoint(sbi, &cpc); 570 write_checkpoint(sbi, &cpc);