From a49324f127dec918f5a3b3f145d0bf2fb81f4588 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 15 Dec 2015 13:29:47 +0800 Subject: f2fs: rename {add,remove,release}_dirty_inode to {add,remove,release}_ino_entry remove_dirty_dir_inode will be renamed to remove_dirty_inode as a generic function in following patch for removing directory/regular/symlink inode in global dirty list. Here rename ino management related functions for readability, also in order to avoid name conflict. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/f2fs/inode.c') diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 97e20decacb4..3d2fe595d078 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -357,9 +357,9 @@ no_delete: if (xnid) invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid); if (is_inode_flag_set(fi, FI_APPEND_WRITE)) - add_dirty_inode(sbi, inode->i_ino, APPEND_INO); + add_ino_entry(sbi, inode->i_ino, APPEND_INO); if (is_inode_flag_set(fi, FI_UPDATE_WRITE)) - add_dirty_inode(sbi, inode->i_ino, UPDATE_INO); + add_ino_entry(sbi, inode->i_ino, UPDATE_INO); if (is_inode_flag_set(fi, FI_FREE_NID)) { if (err && err != -ENOENT) alloc_nid_done(sbi, inode->i_ino); -- cgit v1.2.3 From c227f912732f204c0ec4a577ba812401ac4672af Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Wed, 16 Dec 2015 13:09:20 +0800 Subject: f2fs: record dirty status of regular/symlink inode Maintain regular/symlink inode which has dirty pages in global dirty list and record their total dirty pages count like the way of handling directory inode. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/checkpoint.c | 66 ++++++++++++++++++++++++++-------------------------- fs/f2fs/data.c | 4 ++-- fs/f2fs/dir.c | 2 +- fs/f2fs/f2fs.h | 27 +++++++++++++-------- fs/f2fs/inode.c | 2 +- fs/f2fs/super.c | 6 +++-- 6 files changed, 58 insertions(+), 49 deletions(-) (limited to 'fs/f2fs/inode.c') diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 5008b872f316..a037bbd89dc6 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -722,53 +722,51 @@ fail_no_cp: return -EINVAL; } -static void __add_dirty_inode(struct inode *inode) +static void __add_dirty_inode(struct inode *inode, enum inode_type type) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_inode_info *fi = F2FS_I(inode); + int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE; - if (is_inode_flag_set(fi, FI_DIRTY_DIR)) + if (is_inode_flag_set(fi, flag)) return; - set_inode_flag(fi, FI_DIRTY_DIR); - list_add_tail(&fi->dirty_list, &sbi->dir_inode_list); - stat_inc_dirty_dir(sbi); - return; + set_inode_flag(fi, flag); + list_add_tail(&fi->dirty_list, &sbi->inode_list[type]); + if (type == DIR_INODE) + stat_inc_dirty_dir(sbi); } -static void __remove_dirty_inode(struct inode *inode) +static void __remove_dirty_inode(struct inode *inode, enum inode_type type) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_inode_info *fi = F2FS_I(inode); + int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE; if (get_dirty_pages(inode) || - !is_inode_flag_set(F2FS_I(inode), FI_DIRTY_DIR)) + !is_inode_flag_set(F2FS_I(inode), flag)) return; list_del_init(&fi->dirty_list); - clear_inode_flag(fi, FI_DIRTY_DIR); - stat_dec_dirty_dir(sbi); + clear_inode_flag(fi, flag); + if (type == DIR_INODE) + stat_dec_dirty_dir(sbi); } void update_dirty_page(struct inode *inode, struct page *page) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + enum inode_type type = S_ISDIR(inode->i_mode) ? DIR_INODE : FILE_INODE; if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) return; - if (!S_ISDIR(inode->i_mode)) { - inode_inc_dirty_pages(inode); - goto out; - } - - spin_lock(&sbi->dir_inode_lock); - __add_dirty_inode(inode); + spin_lock(&sbi->inode_lock[type]); + __add_dirty_inode(inode, type); inode_inc_dirty_pages(inode); - spin_unlock(&sbi->dir_inode_lock); + spin_unlock(&sbi->inode_lock[type]); -out: SetPagePrivate(page); f2fs_trace_pid(page); } @@ -777,22 +775,24 @@ void add_dirty_dir_inode(struct inode *inode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - spin_lock(&sbi->dir_inode_lock); - __add_dirty_inode(inode); - spin_unlock(&sbi->dir_inode_lock); + spin_lock(&sbi->inode_lock[DIR_INODE]); + __add_dirty_inode(inode, DIR_INODE); + spin_unlock(&sbi->inode_lock[DIR_INODE]); } -void remove_dirty_dir_inode(struct inode *inode) +void remove_dirty_inode(struct inode *inode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_inode_info *fi = F2FS_I(inode); + enum inode_type type = S_ISDIR(inode->i_mode) ? DIR_INODE : FILE_INODE; - if (!S_ISDIR(inode->i_mode)) + if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) && + !S_ISLNK(inode->i_mode)) return; - spin_lock(&sbi->dir_inode_lock); - __remove_dirty_inode(inode); - spin_unlock(&sbi->dir_inode_lock); + spin_lock(&sbi->inode_lock[type]); + __remove_dirty_inode(inode, type); + spin_unlock(&sbi->inode_lock[type]); /* Only from the recovery routine */ if (is_inode_flag_set(fi, FI_DELAY_IPUT)) { @@ -801,7 +801,7 @@ void remove_dirty_dir_inode(struct inode *inode) } } -void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi) +void sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type) { struct list_head *head; struct inode *inode; @@ -810,16 +810,16 @@ retry: if (unlikely(f2fs_cp_error(sbi))) return; - spin_lock(&sbi->dir_inode_lock); + spin_lock(&sbi->inode_lock[type]); - head = &sbi->dir_inode_list; + head = &sbi->inode_list[type]; if (list_empty(head)) { - spin_unlock(&sbi->dir_inode_lock); + spin_unlock(&sbi->inode_lock[type]); return; } fi = list_entry(head->next, struct f2fs_inode_info, dirty_list); inode = igrab(&fi->vfs_inode); - spin_unlock(&sbi->dir_inode_lock); + spin_unlock(&sbi->inode_lock[type]); if (inode) { filemap_fdatawrite(inode->i_mapping); iput(inode); @@ -854,7 +854,7 @@ retry_flush_dents: /* write all the dirty dentry pages */ if (get_pages(sbi, F2FS_DIRTY_DENTS)) { f2fs_unlock_all(sbi); - sync_dirty_dir_inodes(sbi); + sync_dirty_inodes(sbi, DIR_INODE); if (unlikely(f2fs_cp_error(sbi))) { err = -EIO; goto out; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 90a2ffea875b..292a06cbea07 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1180,7 +1180,7 @@ out: f2fs_balance_fs(sbi); if (wbc->for_reclaim) { f2fs_submit_merged_bio(sbi, DATA, WRITE); - remove_dirty_dir_inode(inode); + remove_dirty_inode(inode); } return 0; @@ -1372,7 +1372,7 @@ static int f2fs_write_data_pages(struct address_space *mapping, if (locked) mutex_unlock(&sbi->writepages); - remove_dirty_dir_inode(inode); + remove_dirty_inode(inode); wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff); return ret; diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 6554fd5fce88..3da58265c0d4 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -444,7 +444,7 @@ error: /* once the failed inode becomes a bad inode, i_mode is S_IFREG */ truncate_inode_pages(&inode->i_data, 0); truncate_blocks(inode, 0, false); - remove_dirty_dir_inode(inode); + remove_dirty_inode(inode); remove_inode_page(inode); return ERR_PTR(err); } diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 37cf04b3ff37..03a2b86a28ba 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -648,6 +648,7 @@ struct f2fs_sm_info { enum count_type { F2FS_WRITEBACK, F2FS_DIRTY_DENTS, + F2FS_DIRTY_DATA, F2FS_DIRTY_NODES, F2FS_DIRTY_META, F2FS_INMEM_PAGES, @@ -696,6 +697,12 @@ struct f2fs_bio_info { struct rw_semaphore io_rwsem; /* blocking op for bio */ }; +enum inode_type { + DIR_INODE, /* for dirty dir inode */ + FILE_INODE, /* for dirty regular/symlink inode */ + NR_INODE_TYPE, +}; + /* for inner inode cache management */ struct inode_management { struct radix_tree_root ino_root; /* ino entry array */ @@ -745,9 +752,9 @@ struct f2fs_sb_info { /* for orphan inode, use 0'th array */ unsigned int max_orphans; /* max orphan inodes */ - /* for directory inode management */ - struct list_head dir_inode_list; /* dir inode list */ - spinlock_t dir_inode_lock; /* for dir inode list lock */ + /* for inode management */ + struct list_head inode_list[NR_INODE_TYPE]; /* dirty inode list */ + spinlock_t inode_lock[NR_INODE_TYPE]; /* for dirty inode list lock */ /* for extent tree cache */ struct radix_tree_root extent_tree_root;/* cache extent cache entries */ @@ -1060,8 +1067,8 @@ static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type) static inline void inode_inc_dirty_pages(struct inode *inode) { atomic_inc(&F2FS_I(inode)->dirty_pages); - if (S_ISDIR(inode->i_mode)) - inc_page_count(F2FS_I_SB(inode), F2FS_DIRTY_DENTS); + inc_page_count(F2FS_I_SB(inode), S_ISDIR(inode->i_mode) ? + F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA); } static inline void dec_page_count(struct f2fs_sb_info *sbi, int count_type) @@ -1076,9 +1083,8 @@ static inline void inode_dec_dirty_pages(struct inode *inode) return; atomic_dec(&F2FS_I(inode)->dirty_pages); - - if (S_ISDIR(inode->i_mode)) - dec_page_count(F2FS_I_SB(inode), F2FS_DIRTY_DENTS); + dec_page_count(F2FS_I_SB(inode), S_ISDIR(inode->i_mode) ? + F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA); } static inline int get_pages(struct f2fs_sb_info *sbi, int count_type) @@ -1417,6 +1423,7 @@ enum { FI_DATA_EXIST, /* indicate data exists */ FI_INLINE_DOTS, /* indicate inline dot dentries */ FI_DO_DEFRAG, /* indicate defragment is running */ + FI_DIRTY_FILE, /* indicate regular/symlink has dirty pages */ }; static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag) @@ -1826,8 +1833,8 @@ int recover_orphan_inodes(struct f2fs_sb_info *); int get_valid_checkpoint(struct f2fs_sb_info *); void update_dirty_page(struct inode *, struct page *); void add_dirty_dir_inode(struct inode *); -void remove_dirty_dir_inode(struct inode *); -void sync_dirty_dir_inodes(struct f2fs_sb_info *); +void remove_dirty_inode(struct inode *); +void sync_dirty_inodes(struct f2fs_sb_info *, enum inode_type); void write_checkpoint(struct f2fs_sb_info *, struct cp_control *); void init_ino_entry_info(struct f2fs_sb_info *); int __init create_checkpoint_caches(void); diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 3d2fe595d078..ec3fb32c4726 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -327,7 +327,7 @@ void f2fs_evict_inode(struct inode *inode) goto out_clear; f2fs_bug_on(sbi, get_dirty_pages(inode)); - remove_dirty_dir_inode(inode); + remove_dirty_inode(inode); f2fs_destroy_extent_tree(inode); diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index bc1a8cd38bc8..5b596d6a8d24 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1339,8 +1339,10 @@ try_onemore: le64_to_cpu(sbi->ckpt->valid_block_count); sbi->last_valid_block_count = sbi->total_valid_block_count; sbi->alloc_valid_block_count = 0; - INIT_LIST_HEAD(&sbi->dir_inode_list); - spin_lock_init(&sbi->dir_inode_lock); + for (i = 0; i < NR_INODE_TYPE; i++) { + INIT_LIST_HEAD(&sbi->inode_list[i]); + spin_lock_init(&sbi->inode_lock[i]); + } init_extent_cache_info(sbi); -- cgit v1.2.3 From ed3d12561a731b99b58c6c95151291cebf0b3feb Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Mon, 28 Dec 2015 11:39:06 -0800 Subject: f2fs: load largest extent all the time Otherwise, we can get mismatched largest extent information. One example is: 1. mount f2fs w/ extent_cache 2. make a small extent 3. umount 4. mount f2fs w/o extent_cache 5. update the largest extent 6. umount 7. mount f2fs w/ extent_cache 8. get the old extent made by #2 Signed-off-by: Jaegeuk Kim --- fs/f2fs/extent_cache.c | 18 +++++++++++++----- fs/f2fs/f2fs.h | 2 +- fs/f2fs/inode.c | 3 ++- 3 files changed, 16 insertions(+), 7 deletions(-) (limited to 'fs/f2fs/inode.c') diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index 5305a29f91a3..b37184f720e8 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -166,20 +166,27 @@ static void __drop_largest_extent(struct inode *inode, largest->len = 0; } -void f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext) +/* return true, if inode page is changed */ +bool f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct extent_tree *et; struct extent_node *en; struct extent_info ei; - if (!f2fs_may_extent_tree(inode)) - return; + if (!f2fs_may_extent_tree(inode)) { + /* drop largest extent */ + if (i_ext && i_ext->len) { + i_ext->len = 0; + return true; + } + return false; + } et = __grab_extent_tree(inode); - if (!i_ext || le32_to_cpu(i_ext->len) < F2FS_MIN_EXTENT_LEN) - return; + if (!i_ext || !i_ext->len) + return false; set_extent_info(&ei, le32_to_cpu(i_ext->fofs), le32_to_cpu(i_ext->blk), le32_to_cpu(i_ext->len)); @@ -196,6 +203,7 @@ void f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext) } out: write_unlock(&et->lock); + return false; } static bool f2fs_lookup_extent_tree(struct inode *inode, pgoff_t pgofs, diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index e04b2be6cd64..a3395088e0f0 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2083,7 +2083,7 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *); * extent_cache.c */ unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *, int); -void f2fs_init_extent_tree(struct inode *, struct f2fs_extent *); +bool f2fs_init_extent_tree(struct inode *, struct f2fs_extent *); unsigned int f2fs_destroy_extent_node(struct inode *); void f2fs_destroy_extent_tree(struct inode *); bool f2fs_lookup_extent_cache(struct inode *, pgoff_t, struct extent_info *); diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index ec3fb32c4726..e95500802daa 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -138,7 +138,8 @@ static int do_read_inode(struct inode *inode) fi->i_pino = le32_to_cpu(ri->i_pino); fi->i_dir_level = ri->i_dir_level; - f2fs_init_extent_tree(inode, &ri->i_ext); + if (f2fs_init_extent_tree(inode, &ri->i_ext)) + set_page_dirty(node_page); get_inline_info(fi, ri); -- cgit v1.2.3 From 12719ae14e57980ebf0a7baa63bc80494c76b192 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 7 Jan 2016 13:23:12 -0800 Subject: f2fs: avoid unnecessary f2fs_balance_fs calls Only when node page is newly dirtied, it needs to check whether we need to do f2fs_gc. Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 4 ++-- fs/f2fs/f2fs.h | 4 ++-- fs/f2fs/inode.c | 19 ++++++++++--------- fs/f2fs/node.c | 26 ++++++++++++++------------ fs/f2fs/node.h | 4 ++-- fs/f2fs/super.c | 2 -- 6 files changed, 30 insertions(+), 29 deletions(-) (limited to 'fs/f2fs/inode.c') diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 77c3bbb9bee0..3cf86fda8138 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -225,8 +225,8 @@ void set_data_blkaddr(struct dnode_of_data *dn) /* Get physical address of data block */ addr_array = blkaddr_in_node(rn); addr_array[ofs_in_node] = cpu_to_le32(dn->data_blkaddr); - set_page_dirty(node_page); - dn->node_changed = true; + if (set_page_dirty(node_page)) + dn->node_changed = true; } int reserve_new_block(struct dnode_of_data *dn) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 882babaa678e..461b32923c14 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1674,8 +1674,8 @@ long f2fs_compat_ioctl(struct file *, unsigned int, unsigned long); void f2fs_set_inode_flags(struct inode *); struct inode *f2fs_iget(struct super_block *, unsigned long); int try_to_free_nats(struct f2fs_sb_info *, int); -void update_inode(struct inode *, struct page *); -void update_inode_page(struct inode *); +int update_inode(struct inode *, struct page *); +int update_inode_page(struct inode *); int f2fs_write_inode(struct inode *, struct writeback_control *); void f2fs_evict_inode(struct inode *); void handle_failed_inode(struct inode *); diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index e95500802daa..cabc1ff108a1 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -222,7 +222,7 @@ bad_inode: return ERR_PTR(ret); } -void update_inode(struct inode *inode, struct page *node_page) +int update_inode(struct inode *inode, struct page *node_page) { struct f2fs_inode *ri; @@ -260,15 +260,16 @@ void update_inode(struct inode *inode, struct page *node_page) __set_inode_rdev(inode, ri); set_cold_node(inode, node_page); - set_page_dirty(node_page); - clear_inode_flag(F2FS_I(inode), FI_DIRTY_INODE); + + return set_page_dirty(node_page); } -void update_inode_page(struct inode *inode) +int update_inode_page(struct inode *inode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct page *node_page; + int ret = 0; retry: node_page = get_node_page(sbi, inode->i_ino); if (IS_ERR(node_page)) { @@ -279,10 +280,11 @@ retry: } else if (err != -ENOENT) { f2fs_stop_checkpoint(sbi); } - return; + return 0; } - update_inode(inode, node_page); + ret = update_inode(inode, node_page); f2fs_put_page(node_page, 1); + return ret; } int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) @@ -300,9 +302,8 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) * We need to balance fs here to prevent from producing dirty node pages * during the urgent cleaning time when runing out of free sections. */ - update_inode_page(inode); - - f2fs_balance_fs(sbi); + if (update_inode_page(inode)) + f2fs_balance_fs(sbi); return 0; } diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 5a2d800f4abc..c091b757bda6 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -543,7 +543,6 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) set_nid(parent, offset[i - 1], nids[i], i == 1); alloc_nid_done(sbi, nids[i]); - dn->node_changed = true; done = true; } else if (mode == LOOKUP_NODE_RA && i == level && level > 1) { npage[i] = get_node_page_ra(parent, offset[i - 1]); @@ -679,8 +678,8 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, ret = truncate_dnode(&rdn); if (ret < 0) goto out_err; - set_nid(page, i, 0, false); - dn->node_changed = true; + if (set_nid(page, i, 0, false)) + dn->node_changed = true; } } else { child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1; @@ -693,8 +692,8 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, rdn.nid = child_nid; ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1); if (ret == (NIDS_PER_BLOCK + 1)) { - set_nid(page, i, 0, false); - dn->node_changed = true; + if (set_nid(page, i, 0, false)) + dn->node_changed = true; child_nofs += ret; } else if (ret < 0 && ret != -ENOENT) { goto out_err; @@ -755,8 +754,8 @@ static int truncate_partial_nodes(struct dnode_of_data *dn, err = truncate_dnode(dn); if (err < 0) goto fail; - set_nid(pages[idx], i, 0, false); - dn->node_changed = true; + if (set_nid(pages[idx], i, 0, false)) + dn->node_changed = true; } if (offset[idx + 1] == 0) { @@ -981,7 +980,8 @@ struct page *new_node_page(struct dnode_of_data *dn, fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); set_cold_node(dn->inode, page); SetPageUptodate(page); - set_page_dirty(page); + if (set_page_dirty(page)) + dn->node_changed = true; if (f2fs_has_xattr_block(ofs)) F2FS_I(dn->inode)->i_xattr_nid = dn->nid; @@ -1138,18 +1138,20 @@ struct page *get_node_page_ra(struct page *parent, int start) void sync_inode_page(struct dnode_of_data *dn) { + int ret = 0; + if (IS_INODE(dn->node_page) || dn->inode_page == dn->node_page) { - update_inode(dn->inode, dn->node_page); + ret = update_inode(dn->inode, dn->node_page); } else if (dn->inode_page) { if (!dn->inode_page_locked) lock_page(dn->inode_page); - update_inode(dn->inode, dn->inode_page); + ret = update_inode(dn->inode, dn->inode_page); if (!dn->inode_page_locked) unlock_page(dn->inode_page); } else { - update_inode_page(dn->inode); + ret = update_inode_page(dn->inode); } - dn->node_changed = true; + dn->node_changed = ret ? true: false; } int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index 2de759a7746f..d4d1f636fe1c 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h @@ -317,7 +317,7 @@ static inline bool IS_DNODE(struct page *node_page) return true; } -static inline void set_nid(struct page *p, int off, nid_t nid, bool i) +static inline int set_nid(struct page *p, int off, nid_t nid, bool i) { struct f2fs_node *rn = F2FS_NODE(p); @@ -327,7 +327,7 @@ static inline void set_nid(struct page *p, int off, nid_t nid, bool i) rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid); else rn->in.nid[off] = cpu_to_le32(nid); - set_page_dirty(p); + return set_page_dirty(p); } static inline nid_t get_nid(struct page *p, int off, bool i) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 0bbd756821a7..f5cc790646e2 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -591,8 +591,6 @@ int f2fs_sync_fs(struct super_block *sb, int sync) mutex_lock(&sbi->gc_mutex); err = write_checkpoint(sbi, &cpc); mutex_unlock(&sbi->gc_mutex); - } else { - f2fs_balance_fs(sbi); } f2fs_trace_ios(NULL, 1); -- cgit v1.2.3 From 2c4db1a6f6b42e2a9fb611cbbeb71a3a9a358ee0 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 7 Jan 2016 14:15:04 -0800 Subject: f2fs: clean up f2fs_balance_fs This patch adds one parameter to clean up all the callers of f2fs_balance_fs. Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 17 ++++++----------- fs/f2fs/f2fs.h | 2 +- fs/f2fs/file.c | 17 ++++++++--------- fs/f2fs/inline.c | 3 +-- fs/f2fs/inode.c | 2 +- fs/f2fs/namei.c | 22 +++++++++++----------- fs/f2fs/segment.c | 6 ++++-- fs/f2fs/xattr.c | 2 +- 8 files changed, 33 insertions(+), 38 deletions(-) (limited to 'fs/f2fs/inode.c') diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 3cf86fda8138..6fae75ddae6d 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -546,8 +546,7 @@ static int __allocate_data_blocks(struct inode *inode, loff_t offset, f2fs_put_dnode(&dn); f2fs_unlock_op(sbi); - if (dn.node_changed) - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, dn.node_changed); } return err; @@ -557,8 +556,7 @@ sync_out: f2fs_put_dnode(&dn); out: f2fs_unlock_op(sbi); - if (dn.node_changed) - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, dn.node_changed); return err; } @@ -657,8 +655,7 @@ get_next: if (create) { f2fs_unlock_op(sbi); - if (dn.node_changed) - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, dn.node_changed); f2fs_lock_op(sbi); } @@ -718,8 +715,7 @@ put_out: unlock_out: if (create) { f2fs_unlock_op(sbi); - if (dn.node_changed) - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, dn.node_changed); } out: trace_f2fs_map_blocks(inode, map, err); @@ -1178,8 +1174,7 @@ out: if (err) ClearPageUptodate(page); unlock_page(page); - if (need_balance_fs) - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, need_balance_fs); if (wbc->for_reclaim || unlikely(f2fs_cp_error(sbi))) { f2fs_submit_merged_bio(sbi, DATA, WRITE); remove_dirty_inode(inode); @@ -1506,7 +1501,7 @@ repeat: if (need_balance && has_not_enough_free_secs(sbi, 0)) { unlock_page(page); - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); lock_page(page); if (page->mapping != mapping) { /* The page got truncated from under us */ diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 461b32923c14..412865482a0b 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1780,7 +1780,7 @@ void destroy_node_manager_caches(void); */ void register_inmem_page(struct inode *, struct page *); int commit_inmem_pages(struct inode *, bool); -void f2fs_balance_fs(struct f2fs_sb_info *); +void f2fs_balance_fs(struct f2fs_sb_info *, bool); void f2fs_balance_fs_bg(struct f2fs_sb_info *); int f2fs_issue_flush(struct f2fs_sb_info *); int create_flush_cmd_control(struct f2fs_sb_info *); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 69bc65fd862c..ff06827aa369 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -55,8 +55,7 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, f2fs_put_dnode(&dn); f2fs_unlock_op(sbi); - if (dn.node_changed) - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, dn.node_changed); file_update_time(vma->vm_file); lock_page(page); @@ -677,7 +676,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr) err = f2fs_truncate(inode, true); if (err) return err; - f2fs_balance_fs(F2FS_I_SB(inode)); + f2fs_balance_fs(F2FS_I_SB(inode), true); } else { /* * do not trim all blocks after i_size if target size is @@ -732,7 +731,7 @@ static int fill_zero(struct inode *inode, pgoff_t index, if (!len) return 0; - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); page = get_new_data_page(inode, NULL, index, false); @@ -818,7 +817,7 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len) loff_t blk_start, blk_end; struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); blk_start = (loff_t)pg_start << PAGE_CACHE_SHIFT; blk_end = (loff_t)pg_end << PAGE_CACHE_SHIFT; @@ -921,7 +920,7 @@ static int f2fs_do_collapse(struct inode *inode, pgoff_t start, pgoff_t end) int ret = 0; for (; end < nrpages; start++, end++) { - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); ret = __exchange_data_block(inode, end, start, true); f2fs_unlock_op(sbi); @@ -1103,7 +1102,7 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len) if (ret) return ret; - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); ret = truncate_blocks(inode, i_size_read(inode), true); if (ret) @@ -1155,7 +1154,7 @@ static int expand_inode_data(struct inode *inode, loff_t offset, if (ret) return ret; - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT; pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT; @@ -1653,7 +1652,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, pg_start = range->start >> PAGE_CACHE_SHIFT; pg_end = (range->start + range->len) >> PAGE_CACHE_SHIFT; - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); mutex_lock(&inode->i_mutex); diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 5ffbd169b719..c3f0b7d4cfca 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -200,8 +200,7 @@ out: f2fs_put_page(page, 1); - if (dn.node_changed) - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, dn.node_changed); return err; } diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index cabc1ff108a1..2ac4b780e8b4 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -303,7 +303,7 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) * during the urgent cleaning time when runing out of free sections. */ if (update_inode_page(inode)) - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); return 0; } diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 0d61a6864ab1..53d6227f5581 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -140,7 +140,7 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode, inode->i_mapping->a_ops = &f2fs_dblock_aops; ino = inode->i_ino; - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); err = f2fs_add_link(dentry, inode); @@ -172,7 +172,7 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir, !f2fs_is_child_context_consistent_with_parent(dir, inode)) return -EPERM; - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); inode->i_ctime = CURRENT_TIME; ihold(inode); @@ -221,7 +221,7 @@ static int __recover_dot_dentries(struct inode *dir, nid_t pino) return 0; } - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); @@ -302,7 +302,7 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) if (!de) goto fail; - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); err = acquire_orphan_inode(sbi); @@ -361,7 +361,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, inode->i_op = &f2fs_symlink_inode_operations; inode->i_mapping->a_ops = &f2fs_dblock_aops; - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); err = f2fs_add_link(dentry, inode); @@ -452,7 +452,7 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) inode->i_mapping->a_ops = &f2fs_dblock_aops; mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_HIGH_ZERO); - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); set_inode_flag(F2FS_I(inode), FI_INC_LINK); f2fs_lock_op(sbi); @@ -498,7 +498,7 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry, init_special_inode(inode, inode->i_mode, rdev); inode->i_op = &f2fs_special_inode_operations; - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); err = f2fs_add_link(dentry, inode); @@ -539,7 +539,7 @@ static int __f2fs_tmpfile(struct inode *dir, struct dentry *dentry, inode->i_mapping->a_ops = &f2fs_dblock_aops; } - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); err = acquire_orphan_inode(sbi); @@ -642,7 +642,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, if (!new_entry) goto out_whiteout; - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); @@ -675,7 +675,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, update_inode_page(old_inode); update_inode_page(new_inode); } else { - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); @@ -816,7 +816,7 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, goto out_new_dir; } - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index a3474bad5770..c7bbc915d962 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -213,7 +213,7 @@ int commit_inmem_pages(struct inode *inode, bool abort) * inode becomes free by iget_locked in f2fs_iget. */ if (!abort) { - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); } @@ -262,8 +262,10 @@ int commit_inmem_pages(struct inode *inode, bool abort) * This function balances dirty node and dentry pages. * In addition, it controls garbage collection. */ -void f2fs_balance_fs(struct f2fs_sb_info *sbi) +void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need) { + if (!need) + return; /* * We should do GC or end up with checkpoint, if there are so many dirty * dir/node pages without enough free segments. diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 862368a32e53..822a8af89c12 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -609,7 +609,7 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name, if (ipage) return __f2fs_setxattr(inode, index, name, value, size, ipage, flags); - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); /* protect xattr_ver */ -- cgit v1.2.3