aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/f2fs/checkpoint.c55
-rw-r--r--fs/f2fs/f2fs.h1
-rw-r--r--fs/f2fs/recovery.c1
3 files changed, 41 insertions, 16 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 6f56e5781dc3..9a7750909221 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -450,13 +450,30 @@ fail_no_cp:
450 return -EINVAL; 450 return -EINVAL;
451} 451}
452 452
453void set_dirty_dir_page(struct inode *inode, struct page *page) 453static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new)
454{ 454{
455 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); 455 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
456 struct list_head *head = &sbi->dir_inode_list; 456 struct list_head *head = &sbi->dir_inode_list;
457 struct dir_inode_entry *new;
458 struct list_head *this; 457 struct list_head *this;
459 458
459 list_for_each(this, head) {
460 struct dir_inode_entry *entry;
461 entry = list_entry(this, struct dir_inode_entry, list);
462 if (entry->inode == inode)
463 return -EEXIST;
464 }
465 list_add_tail(&new->list, head);
466#ifdef CONFIG_F2FS_STAT_FS
467 sbi->n_dirty_dirs++;
468#endif
469 return 0;
470}
471
472void set_dirty_dir_page(struct inode *inode, struct page *page)
473{
474 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
475 struct dir_inode_entry *new;
476
460 if (!S_ISDIR(inode->i_mode)) 477 if (!S_ISDIR(inode->i_mode))
461 return; 478 return;
462retry: 479retry:
@@ -469,25 +486,31 @@ retry:
469 INIT_LIST_HEAD(&new->list); 486 INIT_LIST_HEAD(&new->list);
470 487
471 spin_lock(&sbi->dir_inode_lock); 488 spin_lock(&sbi->dir_inode_lock);
472 list_for_each(this, head) { 489 if (__add_dirty_inode(inode, new))
473 struct dir_inode_entry *entry; 490 kmem_cache_free(inode_entry_slab, new);
474 entry = list_entry(this, struct dir_inode_entry, list);
475 if (entry->inode == inode) {
476 kmem_cache_free(inode_entry_slab, new);
477 goto out;
478 }
479 }
480 list_add_tail(&new->list, head);
481#ifdef CONFIG_F2FS_STAT_FS
482 sbi->n_dirty_dirs++;
483#endif
484 491
485 BUG_ON(!S_ISDIR(inode->i_mode));
486out:
487 inc_page_count(sbi, F2FS_DIRTY_DENTS); 492 inc_page_count(sbi, F2FS_DIRTY_DENTS);
488 inode_inc_dirty_dents(inode); 493 inode_inc_dirty_dents(inode);
489 SetPagePrivate(page); 494 SetPagePrivate(page);
495 spin_unlock(&sbi->dir_inode_lock);
496}
497
498void add_dirty_dir_inode(struct inode *inode)
499{
500 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
501 struct dir_inode_entry *new;
502retry:
503 new = kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
504 if (!new) {
505 cond_resched();
506 goto retry;
507 }
508 new->inode = inode;
509 INIT_LIST_HEAD(&new->list);
490 510
511 spin_lock(&sbi->dir_inode_lock);
512 if (__add_dirty_inode(inode, new))
513 kmem_cache_free(inode_entry_slab, new);
491 spin_unlock(&sbi->dir_inode_lock); 514 spin_unlock(&sbi->dir_inode_lock);
492} 515}
493 516
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 40b137acb8a2..d6e63da513cf 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1030,6 +1030,7 @@ void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
1030int recover_orphan_inodes(struct f2fs_sb_info *); 1030int recover_orphan_inodes(struct f2fs_sb_info *);
1031int get_valid_checkpoint(struct f2fs_sb_info *); 1031int get_valid_checkpoint(struct f2fs_sb_info *);
1032void set_dirty_dir_page(struct inode *, struct page *); 1032void set_dirty_dir_page(struct inode *, struct page *);
1033void add_dirty_dir_inode(struct inode *);
1033void remove_dirty_dir_inode(struct inode *); 1034void remove_dirty_dir_inode(struct inode *);
1034struct inode *check_dirty_dir_inode(struct f2fs_sb_info *, nid_t); 1035struct inode *check_dirty_dir_inode(struct f2fs_sb_info *, nid_t);
1035void sync_dirty_dir_inodes(struct f2fs_sb_info *); 1036void sync_dirty_dir_inodes(struct f2fs_sb_info *);
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 539ca32f4483..ddde14f0eacb 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -58,6 +58,7 @@ static int recover_dentry(struct page *ipage, struct inode *inode)
58 goto out; 58 goto out;
59 } 59 }
60 set_inode_flag(F2FS_I(dir), FI_DELAY_IPUT); 60 set_inode_flag(F2FS_I(dir), FI_DELAY_IPUT);
61 add_dirty_dir_inode(dir);
61 } 62 }
62 63
63 name.len = le32_to_cpu(raw_inode->i_namelen); 64 name.len = le32_to_cpu(raw_inode->i_namelen);