summaryrefslogtreecommitdiffstats
path: root/fs/f2fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/f2fs')
-rw-r--r--fs/f2fs/checkpoint.c7
-rw-r--r--fs/f2fs/data.c74
-rw-r--r--fs/f2fs/f2fs.h3
-rw-r--r--fs/f2fs/node.c15
-rw-r--r--fs/f2fs/segment.c6
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