diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-03-20 08:52:53 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-03-20 09:10:11 -0400 |
commit | 479f40c44ae30e02642ce0391be707a53852d545 (patch) | |
tree | 0ad83458da430f524f70a681c4d88c1b22e54233 /fs/f2fs/node.c | |
parent | d928bfbfe77aa457b765c19e9db8cd4cc72b3c89 (diff) |
f2fs: skip unnecessary node writes during fsync
If multiple redundant fsync calls are triggered, we don't need to write its
node pages with fsync mark continuously.
So, this patch adds FI_NEED_FSYNC to track whether the latest node block is
written with the fsync mark or not.
If the mark was set, a new fsync doesn't need to write a node block.
Otherwise, we should do a new node block with the mark for roll-forward
recovery.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/node.c')
-rw-r--r-- | fs/f2fs/node.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index daf644c57eae..eced8d7bf502 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c | |||
@@ -133,6 +133,20 @@ int is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid) | |||
133 | return is_cp; | 133 | return is_cp; |
134 | } | 134 | } |
135 | 135 | ||
136 | bool fsync_mark_done(struct f2fs_sb_info *sbi, nid_t nid) | ||
137 | { | ||
138 | struct f2fs_nm_info *nm_i = NM_I(sbi); | ||
139 | struct nat_entry *e; | ||
140 | bool fsync_done = false; | ||
141 | |||
142 | read_lock(&nm_i->nat_tree_lock); | ||
143 | e = __lookup_nat_cache(nm_i, nid); | ||
144 | if (e) | ||
145 | fsync_done = e->fsync_done; | ||
146 | read_unlock(&nm_i->nat_tree_lock); | ||
147 | return fsync_done; | ||
148 | } | ||
149 | |||
136 | static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid) | 150 | static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid) |
137 | { | 151 | { |
138 | struct nat_entry *new; | 152 | struct nat_entry *new; |
@@ -173,7 +187,7 @@ retry: | |||
173 | } | 187 | } |
174 | 188 | ||
175 | static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni, | 189 | static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni, |
176 | block_t new_blkaddr) | 190 | block_t new_blkaddr, bool fsync_done) |
177 | { | 191 | { |
178 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 192 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
179 | struct nat_entry *e; | 193 | struct nat_entry *e; |
@@ -217,6 +231,11 @@ retry: | |||
217 | /* change address */ | 231 | /* change address */ |
218 | nat_set_blkaddr(e, new_blkaddr); | 232 | nat_set_blkaddr(e, new_blkaddr); |
219 | __set_nat_cache_dirty(nm_i, e); | 233 | __set_nat_cache_dirty(nm_i, e); |
234 | |||
235 | /* update fsync_mark if its inode nat entry is still alive */ | ||
236 | e = __lookup_nat_cache(nm_i, ni->ino); | ||
237 | if (e) | ||
238 | e->fsync_done = fsync_done; | ||
220 | write_unlock(&nm_i->nat_tree_lock); | 239 | write_unlock(&nm_i->nat_tree_lock); |
221 | } | 240 | } |
222 | 241 | ||
@@ -483,7 +502,7 @@ static void truncate_node(struct dnode_of_data *dn) | |||
483 | /* Deallocate node address */ | 502 | /* Deallocate node address */ |
484 | invalidate_blocks(sbi, ni.blk_addr); | 503 | invalidate_blocks(sbi, ni.blk_addr); |
485 | dec_valid_node_count(sbi, dn->inode); | 504 | dec_valid_node_count(sbi, dn->inode); |
486 | set_node_addr(sbi, &ni, NULL_ADDR); | 505 | set_node_addr(sbi, &ni, NULL_ADDR, false); |
487 | 506 | ||
488 | if (dn->nid == dn->inode->i_ino) { | 507 | if (dn->nid == dn->inode->i_ino) { |
489 | remove_orphan_inode(sbi, dn->nid); | 508 | remove_orphan_inode(sbi, dn->nid); |
@@ -846,7 +865,7 @@ struct page *new_node_page(struct dnode_of_data *dn, | |||
846 | f2fs_bug_on(old_ni.blk_addr != NULL_ADDR); | 865 | f2fs_bug_on(old_ni.blk_addr != NULL_ADDR); |
847 | new_ni = old_ni; | 866 | new_ni = old_ni; |
848 | new_ni.ino = dn->inode->i_ino; | 867 | new_ni.ino = dn->inode->i_ino; |
849 | set_node_addr(sbi, &new_ni, NEW_ADDR); | 868 | set_node_addr(sbi, &new_ni, NEW_ADDR, false); |
850 | 869 | ||
851 | fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); | 870 | fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); |
852 | set_cold_node(dn->inode, page); | 871 | set_cold_node(dn->inode, page); |
@@ -1202,7 +1221,7 @@ static int f2fs_write_node_page(struct page *page, | |||
1202 | mutex_lock(&sbi->node_write); | 1221 | mutex_lock(&sbi->node_write); |
1203 | set_page_writeback(page); | 1222 | set_page_writeback(page); |
1204 | write_node_page(sbi, page, &fio, nid, ni.blk_addr, &new_addr); | 1223 | write_node_page(sbi, page, &fio, nid, ni.blk_addr, &new_addr); |
1205 | set_node_addr(sbi, &ni, new_addr); | 1224 | set_node_addr(sbi, &ni, new_addr, is_fsync_dnode(page)); |
1206 | dec_page_count(sbi, F2FS_DIRTY_NODES); | 1225 | dec_page_count(sbi, F2FS_DIRTY_NODES); |
1207 | mutex_unlock(&sbi->node_write); | 1226 | mutex_unlock(&sbi->node_write); |
1208 | unlock_page(page); | 1227 | unlock_page(page); |
@@ -1503,7 +1522,7 @@ void recover_node_page(struct f2fs_sb_info *sbi, struct page *page, | |||
1503 | block_t new_blkaddr) | 1522 | block_t new_blkaddr) |
1504 | { | 1523 | { |
1505 | rewrite_node_page(sbi, page, sum, ni->blk_addr, new_blkaddr); | 1524 | rewrite_node_page(sbi, page, sum, ni->blk_addr, new_blkaddr); |
1506 | set_node_addr(sbi, ni, new_blkaddr); | 1525 | set_node_addr(sbi, ni, new_blkaddr, false); |
1507 | clear_node_page_dirty(page); | 1526 | clear_node_page_dirty(page); |
1508 | } | 1527 | } |
1509 | 1528 | ||
@@ -1559,7 +1578,7 @@ bool recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr) | |||
1559 | f2fs_bug_on(ni.blk_addr == NULL_ADDR); | 1578 | f2fs_bug_on(ni.blk_addr == NULL_ADDR); |
1560 | invalidate_blocks(sbi, ni.blk_addr); | 1579 | invalidate_blocks(sbi, ni.blk_addr); |
1561 | dec_valid_node_count(sbi, inode); | 1580 | dec_valid_node_count(sbi, inode); |
1562 | set_node_addr(sbi, &ni, NULL_ADDR); | 1581 | set_node_addr(sbi, &ni, NULL_ADDR, false); |
1563 | 1582 | ||
1564 | recover_xnid: | 1583 | recover_xnid: |
1565 | /* 2: allocate new xattr nid */ | 1584 | /* 2: allocate new xattr nid */ |
@@ -1569,12 +1588,12 @@ recover_xnid: | |||
1569 | remove_free_nid(NM_I(sbi), new_xnid); | 1588 | remove_free_nid(NM_I(sbi), new_xnid); |
1570 | get_node_info(sbi, new_xnid, &ni); | 1589 | get_node_info(sbi, new_xnid, &ni); |
1571 | ni.ino = inode->i_ino; | 1590 | ni.ino = inode->i_ino; |
1572 | set_node_addr(sbi, &ni, NEW_ADDR); | 1591 | set_node_addr(sbi, &ni, NEW_ADDR, false); |
1573 | F2FS_I(inode)->i_xattr_nid = new_xnid; | 1592 | F2FS_I(inode)->i_xattr_nid = new_xnid; |
1574 | 1593 | ||
1575 | /* 3: update xattr blkaddr */ | 1594 | /* 3: update xattr blkaddr */ |
1576 | refresh_sit_entry(sbi, NEW_ADDR, blkaddr); | 1595 | refresh_sit_entry(sbi, NEW_ADDR, blkaddr); |
1577 | set_node_addr(sbi, &ni, blkaddr); | 1596 | set_node_addr(sbi, &ni, blkaddr, false); |
1578 | 1597 | ||
1579 | update_inode_page(inode); | 1598 | update_inode_page(inode); |
1580 | return true; | 1599 | return true; |
@@ -1612,7 +1631,7 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) | |||
1612 | 1631 | ||
1613 | if (unlikely(!inc_valid_node_count(sbi, NULL))) | 1632 | if (unlikely(!inc_valid_node_count(sbi, NULL))) |
1614 | WARN_ON(1); | 1633 | WARN_ON(1); |
1615 | set_node_addr(sbi, &new_ni, NEW_ADDR); | 1634 | set_node_addr(sbi, &new_ni, NEW_ADDR, false); |
1616 | inc_valid_inode_count(sbi); | 1635 | inc_valid_inode_count(sbi); |
1617 | f2fs_put_page(ipage, 1); | 1636 | f2fs_put_page(ipage, 1); |
1618 | return 0; | 1637 | return 0; |