diff options
-rw-r--r-- | fs/f2fs/checkpoint.c | 55 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 1 | ||||
-rw-r--r-- | fs/f2fs/recovery.c | 1 |
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 | ||
453 | void set_dirty_dir_page(struct inode *inode, struct page *page) | 453 | static 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 | |||
472 | void 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; |
462 | retry: | 479 | retry: |
@@ -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)); | ||
486 | out: | ||
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 | |||
498 | void 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; | ||
502 | retry: | ||
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); | |||
1030 | int recover_orphan_inodes(struct f2fs_sb_info *); | 1030 | int recover_orphan_inodes(struct f2fs_sb_info *); |
1031 | int get_valid_checkpoint(struct f2fs_sb_info *); | 1031 | int get_valid_checkpoint(struct f2fs_sb_info *); |
1032 | void set_dirty_dir_page(struct inode *, struct page *); | 1032 | void set_dirty_dir_page(struct inode *, struct page *); |
1033 | void add_dirty_dir_inode(struct inode *); | ||
1033 | void remove_dirty_dir_inode(struct inode *); | 1034 | void remove_dirty_dir_inode(struct inode *); |
1034 | struct inode *check_dirty_dir_inode(struct f2fs_sb_info *, nid_t); | 1035 | struct inode *check_dirty_dir_inode(struct f2fs_sb_info *, nid_t); |
1035 | void sync_dirty_dir_inodes(struct f2fs_sb_info *); | 1036 | void 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); |