diff options
Diffstat (limited to 'fs/f2fs')
-rw-r--r-- | fs/f2fs/checkpoint.c | 7 | ||||
-rw-r--r-- | fs/f2fs/data.c | 74 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 3 | ||||
-rw-r--r-- | fs/f2fs/node.c | 15 | ||||
-rw-r--r-- | fs/f2fs/segment.c | 6 |
5 files changed, 79 insertions, 26 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 96d606d93f2f..9c0d721598e5 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -234,10 +234,15 @@ static int f2fs_write_meta_page(struct page *page, write_meta_page(sbi, page); dec_page_count(sbi, F2FS_DIRTY_META); + + if (wbc->for_reclaim) + f2fs_submit_merged_bio_cond(sbi, NULL, page, 0, META, WRITE); + unlock_page(page); - if (wbc->for_reclaim || unlikely(f2fs_cp_error(sbi))) + if (unlikely(f2fs_cp_error(sbi))) f2fs_submit_merged_bio(sbi, META, WRITE); + return 0; redirty_out: diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e0b09c33fc0f..9ae43a725d54 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -114,20 +114,18 @@ static void __submit_merged_bio(struct f2fs_bio_info *io) io->bio = NULL; } -bool is_merged_page(struct f2fs_sb_info *sbi, struct page *page, - enum page_type type) +static bool __has_merged_page(struct f2fs_bio_info *io, struct inode *inode, + struct page *page, nid_t ino) { - enum page_type btype = PAGE_TYPE_OF_BIO(type); - struct f2fs_bio_info *io = &sbi->write_io[btype]; struct bio_vec *bvec; struct page *target; int i; - down_read(&io->io_rwsem); - if (!io->bio) { - up_read(&io->io_rwsem); + if (!io->bio) return false; - } + + if (!inode && !page && !ino) + return true; bio_for_each_segment_all(bvec, io->bio, i) { @@ -142,18 +140,34 @@ bool is_merged_page(struct f2fs_sb_info *sbi, struct page *page, target = ctx->w.control_page; } - if (page == target) { - up_read(&io->io_rwsem); + if (inode && inode == target->mapping->host) + return true; + if (page && page == target) + return true; + if (ino && ino == ino_of_node(target)) return true; - } } - up_read(&io->io_rwsem); return false; } -void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, - enum page_type type, int rw) +static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode, + struct page *page, nid_t ino, + enum page_type type) +{ + enum page_type btype = PAGE_TYPE_OF_BIO(type); + struct f2fs_bio_info *io = &sbi->write_io[btype]; + bool ret; + + down_read(&io->io_rwsem); + ret = __has_merged_page(io, inode, page, ino); + up_read(&io->io_rwsem); + return ret; +} + +static void __f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, + struct inode *inode, struct page *page, + nid_t ino, enum page_type type, int rw) { enum page_type btype = PAGE_TYPE_OF_BIO(type); struct f2fs_bio_info *io; @@ -162,6 +176,9 @@ void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, down_write(&io->io_rwsem); + if (!__has_merged_page(io, inode, page, ino)) + goto out; + /* change META to META_FLUSH in the checkpoint procedure */ if (type >= META_FLUSH) { io->fio.type = META_FLUSH; @@ -171,9 +188,24 @@ void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, io->fio.rw = WRITE_FLUSH_FUA | REQ_META | REQ_PRIO; } __submit_merged_bio(io); +out: up_write(&io->io_rwsem); } +void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, enum page_type type, + int rw) +{ + __f2fs_submit_merged_bio(sbi, NULL, NULL, 0, type, rw); +} + +void f2fs_submit_merged_bio_cond(struct f2fs_sb_info *sbi, + struct inode *inode, struct page *page, + nid_t ino, enum page_type type, int rw) +{ + if (has_merged_page(sbi, inode, page, ino, type)) + __f2fs_submit_merged_bio(sbi, inode, page, ino, type, rw); +} + /* * Fill the locked page with data located in the block address. * Return unlocked page. @@ -1140,12 +1172,18 @@ out: inode_dec_dirty_pages(inode); if (err) ClearPageUptodate(page); + + if (wbc->for_reclaim) { + f2fs_submit_merged_bio_cond(sbi, NULL, page, 0, DATA, WRITE); + remove_dirty_inode(inode); + } + unlock_page(page); f2fs_balance_fs(sbi, need_balance_fs); - if (wbc->for_reclaim || unlikely(f2fs_cp_error(sbi))) { + + if (unlikely(f2fs_cp_error(sbi))) f2fs_submit_merged_bio(sbi, DATA, WRITE); - remove_dirty_inode(inode); - } + return 0; redirty_out: @@ -1333,7 +1371,7 @@ static int f2fs_write_data_pages(struct address_space *mapping, locked = true; } ret = f2fs_write_cache_pages(mapping, wbc, __f2fs_writepage, mapping); - f2fs_submit_merged_bio(sbi, DATA, WRITE); + f2fs_submit_merged_bio_cond(sbi, inode, NULL, 0, DATA, WRITE); if (locked) mutex_unlock(&sbi->writepages); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 469a1f49a3cd..5f98236f4d58 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1897,8 +1897,9 @@ void destroy_checkpoint_caches(void); /* * data.c */ -bool is_merged_page(struct f2fs_sb_info *, struct page *, enum page_type); void f2fs_submit_merged_bio(struct f2fs_sb_info *, enum page_type, int); +void f2fs_submit_merged_bio_cond(struct f2fs_sb_info *, struct inode *, + struct page *, nid_t, enum page_type, int); int f2fs_submit_page_bio(struct f2fs_io_info *); void f2fs_submit_page_mbio(struct f2fs_io_info *); void set_data_blkaddr(struct dnode_of_data *); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 511c0e7c3ae1..e08b8d5e8ca2 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1337,8 +1337,13 @@ continue_unlock: goto next_step; } - if (wrote) - f2fs_submit_merged_bio(sbi, NODE, WRITE); + if (wrote) { + if (ino) + f2fs_submit_merged_bio_cond(sbi, NULL, NULL, + ino, NODE, WRITE); + else + f2fs_submit_merged_bio(sbi, NODE, WRITE); + } return nwritten; } @@ -1433,9 +1438,13 @@ static int f2fs_write_node_page(struct page *page, set_node_addr(sbi, &ni, fio.blk_addr, is_fsync_dnode(page)); dec_page_count(sbi, F2FS_DIRTY_NODES); up_read(&sbi->node_write); + + if (wbc->for_reclaim) + f2fs_submit_merged_bio_cond(sbi, NULL, page, 0, NODE, WRITE); + unlock_page(page); - if (wbc->for_reclaim || unlikely(f2fs_cp_error(sbi))) + if (unlikely(f2fs_cp_error(sbi))) f2fs_submit_merged_bio(sbi, NODE, WRITE); return 0; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 7cd07d54be4e..57a5f7bb275a 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -254,7 +254,8 @@ int commit_inmem_pages(struct inode *inode, bool abort) if (!abort) { f2fs_unlock_op(sbi); if (submit_bio) - f2fs_submit_merged_bio(sbi, DATA, WRITE); + f2fs_submit_merged_bio_cond(sbi, inode, NULL, 0, + DATA, WRITE); } return err; } @@ -1422,8 +1423,7 @@ void f2fs_wait_on_page_writeback(struct page *page, if (PageWriteback(page)) { struct f2fs_sb_info *sbi = F2FS_P_SB(page); - if (is_merged_page(sbi, page, type)) - f2fs_submit_merged_bio(sbi, type, WRITE); + f2fs_submit_merged_bio_cond(sbi, NULL, page, 0, type, WRITE); if (ordered) wait_on_page_writeback(page); else |