Commit 479f40c44ae30e02642ce0391be707a53852d545

Authored by Jaegeuk Kim
1 parent d928bfbfe7

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>

Showing 4 changed files with 32 additions and 9 deletions Side-by-side Diff

... ... @@ -1126,6 +1126,7 @@
1126 1126 struct node_info;
1127 1127  
1128 1128 int is_checkpointed_node(struct f2fs_sb_info *, nid_t);
  1129 +bool fsync_mark_done(struct f2fs_sb_info *, nid_t);
1129 1130 void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *);
1130 1131 int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int);
1131 1132 int truncate_inode_blocks(struct inode *, pgoff_t);
... ... @@ -176,6 +176,8 @@
176 176 } else {
177 177 /* if there is no written node page, write its inode page */
178 178 while (!sync_node_pages(sbi, inode->i_ino, &wbc)) {
  179 + if (fsync_mark_done(sbi, inode->i_ino))
  180 + goto out;
179 181 mark_inode_dirty_sync(inode);
180 182 ret = f2fs_write_inode(inode, NULL);
181 183 if (ret)
... ... @@ -133,6 +133,20 @@
133 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 150 static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid)
137 151 {
138 152 struct nat_entry *new;
... ... @@ -173,7 +187,7 @@
173 187 }
174 188  
175 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 192 struct f2fs_nm_info *nm_i = NM_I(sbi);
179 193 struct nat_entry *e;
... ... @@ -217,6 +231,11 @@
217 231 /* change address */
218 232 nat_set_blkaddr(e, new_blkaddr);
219 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 239 write_unlock(&nm_i->nat_tree_lock);
221 240 }
222 241  
... ... @@ -483,7 +502,7 @@
483 502 /* Deallocate node address */
484 503 invalidate_blocks(sbi, ni.blk_addr);
485 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 507 if (dn->nid == dn->inode->i_ino) {
489 508 remove_orphan_inode(sbi, dn->nid);
... ... @@ -846,7 +865,7 @@
846 865 f2fs_bug_on(old_ni.blk_addr != NULL_ADDR);
847 866 new_ni = old_ni;
848 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 870 fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true);
852 871 set_cold_node(dn->inode, page);
... ... @@ -1202,7 +1221,7 @@
1202 1221 mutex_lock(&sbi->node_write);
1203 1222 set_page_writeback(page);
1204 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 1225 dec_page_count(sbi, F2FS_DIRTY_NODES);
1207 1226 mutex_unlock(&sbi->node_write);
1208 1227 unlock_page(page);
... ... @@ -1503,7 +1522,7 @@
1503 1522 block_t new_blkaddr)
1504 1523 {
1505 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 1526 clear_node_page_dirty(page);
1508 1527 }
1509 1528  
... ... @@ -1559,7 +1578,7 @@
1559 1578 f2fs_bug_on(ni.blk_addr == NULL_ADDR);
1560 1579 invalidate_blocks(sbi, ni.blk_addr);
1561 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 1583 recover_xnid:
1565 1584 /* 2: allocate new xattr nid */
1566 1585  
... ... @@ -1569,12 +1588,12 @@
1569 1588 remove_free_nid(NM_I(sbi), new_xnid);
1570 1589 get_node_info(sbi, new_xnid, &ni);
1571 1590 ni.ino = inode->i_ino;
1572   - set_node_addr(sbi, &ni, NEW_ADDR);
  1591 + set_node_addr(sbi, &ni, NEW_ADDR, false);
1573 1592 F2FS_I(inode)->i_xattr_nid = new_xnid;
1574 1593  
1575 1594 /* 3: update xattr blkaddr */
1576 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 1598 update_inode_page(inode);
1580 1599 return true;
... ... @@ -1612,7 +1631,7 @@
1612 1631  
1613 1632 if (unlikely(!inc_valid_node_count(sbi, NULL)))
1614 1633 WARN_ON(1);
1615   - set_node_addr(sbi, &new_ni, NEW_ADDR);
  1634 + set_node_addr(sbi, &new_ni, NEW_ADDR, false);
1616 1635 inc_valid_inode_count(sbi);
1617 1636 f2fs_put_page(ipage, 1);
1618 1637 return 0;
... ... @@ -42,6 +42,7 @@
42 42 struct nat_entry {
43 43 struct list_head list; /* for clean or dirty nat list */
44 44 bool checkpointed; /* whether it is checkpointed or not */
  45 + bool fsync_done; /* whether the latest node has fsync mark */
45 46 struct node_info ni; /* in-memory node information */
46 47 };
47 48