summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/f2fs/data.c18
-rw-r--r--fs/f2fs/f2fs.h8
-rw-r--r--fs/f2fs/gc.c6
-rw-r--r--fs/f2fs/segment.c27
4 files changed, 37 insertions, 22 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 5607393198df..fb5e5c2627e5 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -194,8 +194,9 @@ void f2fs_submit_page_mbio(struct f2fs_sb_info *sbi, struct page *page,
if (!is_read_io(rw))
inc_page_count(sbi, F2FS_WRITEBACK);
- if (io->bio && io->last_block_in_bio != blk_addr - 1)
- __submit_merged_bio(sbi, io, type, true, rw);
+ if (io->bio && (io->last_block_in_bio != blk_addr - 1 ||
+ io->rw_flag != rw))
+ __submit_merged_bio(sbi, io, type, false, io->rw_flag);
alloc_new:
if (io->bio == NULL) {
bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi));
@@ -203,6 +204,7 @@ alloc_new:
io->bio->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
io->bio->bi_end_io = is_read_io(rw) ? f2fs_read_end_io :
f2fs_write_end_io;
+ io->rw_flag = rw;
/*
* The end_io will be assigned at the sumbission phase.
* Until then, let bio_add_page() merge consecutive IOs as much
@@ -212,7 +214,7 @@ alloc_new:
if (bio_add_page(io->bio, page, PAGE_CACHE_SIZE, 0) <
PAGE_CACHE_SIZE) {
- __submit_merged_bio(sbi, io, type, true, rw);
+ __submit_merged_bio(sbi, io, type, false, rw);
goto alloc_new;
}
@@ -641,7 +643,7 @@ static int f2fs_read_data_pages(struct file *file,
return mpage_readpages(mapping, pages, nr_pages, get_data_block_ro);
}
-int do_write_data_page(struct page *page)
+int do_write_data_page(struct page *page, struct writeback_control *wbc)
{
struct inode *inode = page->mapping->host;
block_t old_blk_addr, new_blk_addr;
@@ -669,10 +671,10 @@ int do_write_data_page(struct page *page)
!is_cold_data(page) &&
need_inplace_update(inode))) {
rewrite_data_page(F2FS_SB(inode->i_sb), page,
- old_blk_addr);
+ old_blk_addr, wbc);
} else {
write_data_page(inode, page, &dn,
- old_blk_addr, &new_blk_addr);
+ old_blk_addr, &new_blk_addr, wbc);
update_extent_cache(new_blk_addr, &dn);
}
out_writepage:
@@ -719,10 +721,10 @@ write:
if (S_ISDIR(inode->i_mode)) {
dec_page_count(sbi, F2FS_DIRTY_DENTS);
inode_dec_dirty_dents(inode);
- err = do_write_data_page(page);
+ err = do_write_data_page(page, wbc);
} else {
f2fs_lock_op(sbi);
- err = do_write_data_page(page);
+ err = do_write_data_page(page, wbc);
f2fs_unlock_op(sbi);
need_balance_fs = true;
}
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index dca18b3bcc62..b1df239ba421 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -368,6 +368,7 @@ enum page_type {
struct f2fs_bio_info {
struct bio *bio; /* bios to merge */
sector_t last_block_in_bio; /* last block number */
+ int rw_flag; /* rw flag for all pages */
struct mutex io_mutex; /* mutex for bio */
};
@@ -1098,8 +1099,9 @@ void write_meta_page(struct f2fs_sb_info *, struct page *);
void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int,
block_t, block_t *);
void write_data_page(struct inode *, struct page *, struct dnode_of_data*,
- block_t, block_t *);
-void rewrite_data_page(struct f2fs_sb_info *, struct page *, block_t);
+ block_t, block_t *, struct writeback_control *);
+void rewrite_data_page(struct f2fs_sb_info *, struct page *, block_t,
+ struct writeback_control *);
void recover_data_page(struct f2fs_sb_info *, struct page *,
struct f2fs_summary *, block_t, block_t);
void rewrite_node_page(struct f2fs_sb_info *, struct page *,
@@ -1150,7 +1152,7 @@ void update_extent_cache(block_t, struct dnode_of_data *);
struct page *find_data_page(struct inode *, pgoff_t, bool);
struct page *get_lock_data_page(struct inode *, pgoff_t);
struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool);
-int do_write_data_page(struct page *);
+int do_write_data_page(struct page *, struct writeback_control *);
/*
* gc.c
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 29ceb9d71c8c..c68fba5ffadb 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -520,6 +520,10 @@ static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
static void move_data_page(struct inode *inode, struct page *page, int gc_type)
{
+ struct writeback_control wbc = {
+ .sync_mode = 1,
+ };
+
if (gc_type == BG_GC) {
if (PageWriteback(page))
goto out;
@@ -536,7 +540,7 @@ static void move_data_page(struct inode *inode, struct page *page, int gc_type)
inode_dec_dirty_dents(inode);
}
set_cold_data(page);
- do_write_data_page(page);
+ do_write_data_page(page, &wbc);
clear_cold_data(page);
}
out:
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index ca9adf5914cc..e5dc41114867 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -856,12 +856,13 @@ static int __get_segment_type(struct page *page, enum page_type p_type)
static void do_write_page(struct f2fs_sb_info *sbi, struct page *page,
block_t old_blkaddr, block_t *new_blkaddr,
- struct f2fs_summary *sum, enum page_type p_type)
+ struct f2fs_summary *sum, enum page_type p_type,
+ struct writeback_control *wbc)
{
struct sit_info *sit_i = SIT_I(sbi);
struct curseg_info *curseg;
unsigned int old_cursegno;
- int type;
+ int type, rw = WRITE;
type = __get_segment_type(page, p_type);
curseg = CURSEG_I(sbi, type);
@@ -900,7 +901,9 @@ static void do_write_page(struct f2fs_sb_info *sbi, struct page *page,
fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg));
/* writeout dirty page into bdev */
- f2fs_submit_page_mbio(sbi, page, *new_blkaddr, p_type, WRITE);
+ if (wbc->sync_mode == WB_SYNC_ALL)
+ rw |= WRITE_SYNC;
+ f2fs_submit_page_mbio(sbi, page, *new_blkaddr, p_type, rw);
mutex_unlock(&curseg->curseg_mutex);
}
@@ -915,13 +918,16 @@ void write_node_page(struct f2fs_sb_info *sbi, struct page *page,
unsigned int nid, block_t old_blkaddr, block_t *new_blkaddr)
{
struct f2fs_summary sum;
+ struct writeback_control wbc = {
+ .sync_mode = 1,
+ };
set_summary(&sum, nid, 0, 0);
- do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, NODE);
+ do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, NODE, &wbc);
}
void write_data_page(struct inode *inode, struct page *page,
struct dnode_of_data *dn, block_t old_blkaddr,
- block_t *new_blkaddr)
+ block_t *new_blkaddr, struct writeback_control *wbc)
{
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
struct f2fs_summary sum;
@@ -932,13 +938,14 @@ void write_data_page(struct inode *inode, struct page *page,
set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
do_write_page(sbi, page, old_blkaddr,
- new_blkaddr, &sum, DATA);
+ new_blkaddr, &sum, DATA, wbc);
}
void rewrite_data_page(struct f2fs_sb_info *sbi, struct page *page,
- block_t old_blk_addr)
+ block_t old_blk_addr, struct writeback_control *wbc)
{
- f2fs_submit_page_mbio(sbi, page, old_blk_addr, DATA, WRITE);
+ int rw = wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE;
+ f2fs_submit_page_mbio(sbi, page, old_blk_addr, DATA, rw);
}
void recover_data_page(struct f2fs_sb_info *sbi,
@@ -1025,7 +1032,7 @@ void rewrite_node_page(struct f2fs_sb_info *sbi,
/* rewrite node page */
set_page_writeback(page);
- f2fs_submit_page_mbio(sbi, page, new_blkaddr, NODE, WRITE);
+ f2fs_submit_page_mbio(sbi, page, new_blkaddr, NODE, WRITE_SYNC);
f2fs_submit_merged_bio(sbi, NODE, true, WRITE);
refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
@@ -1593,7 +1600,7 @@ repeat:
continue;
}
- f2fs_submit_page_mbio(sbi, page, blk_addr, META, READ);
+ f2fs_submit_page_mbio(sbi, page, blk_addr, META, READ_SYNC);
mark_page_accessed(page);
f2fs_put_page(page, 0);