ソースを参照

f2fs: check last page index in cached bio to decide submission

If the cached bio has the last page's index, then we need to submit it.
Otherwise, we don't need to submit it and can wait for further IO merges.

Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Jaegeuk Kim 8 年 前
コミット
942fd3192f
5 ファイル変更40 行追加35 行削除
  1. 2 1
      fs/f2fs/checkpoint.c
  2. 22 21
      fs/f2fs/data.c
  3. 2 2
      fs/f2fs/f2fs.h
  4. 7 5
      fs/f2fs/node.c
  5. 7 6
      fs/f2fs/segment.c

+ 2 - 1
fs/f2fs/checkpoint.c

@@ -249,7 +249,8 @@ static int f2fs_write_meta_page(struct page *page,
 	dec_page_count(sbi, F2FS_DIRTY_META);
 	dec_page_count(sbi, F2FS_DIRTY_META);
 
 
 	if (wbc->for_reclaim)
 	if (wbc->for_reclaim)
-		f2fs_submit_merged_bio_cond(sbi, NULL, page, 0, META, WRITE);
+		f2fs_submit_merged_bio_cond(sbi, page->mapping->host,
+						0, page->index, META, WRITE);
 
 
 	unlock_page(page);
 	unlock_page(page);
 
 

+ 22 - 21
fs/f2fs/data.c

@@ -243,8 +243,8 @@ static void __submit_merged_bio(struct f2fs_bio_info *io)
 	io->bio = NULL;
 	io->bio = NULL;
 }
 }
 
 
-static bool __has_merged_page(struct f2fs_bio_info *io, struct inode *inode,
-						struct page *page, nid_t ino)
+static bool __has_merged_page(struct f2fs_bio_info *io,
+				struct inode *inode, nid_t ino, pgoff_t idx)
 {
 {
 	struct bio_vec *bvec;
 	struct bio_vec *bvec;
 	struct page *target;
 	struct page *target;
@@ -253,7 +253,7 @@ static bool __has_merged_page(struct f2fs_bio_info *io, struct inode *inode,
 	if (!io->bio)
 	if (!io->bio)
 		return false;
 		return false;
 
 
-	if (!inode && !page && !ino)
+	if (!inode && !ino)
 		return true;
 		return true;
 
 
 	bio_for_each_segment_all(bvec, io->bio, i) {
 	bio_for_each_segment_all(bvec, io->bio, i) {
@@ -263,10 +263,11 @@ static bool __has_merged_page(struct f2fs_bio_info *io, struct inode *inode,
 		else
 		else
 			target = fscrypt_control_page(bvec->bv_page);
 			target = fscrypt_control_page(bvec->bv_page);
 
 
+		if (idx != target->index)
+			continue;
+
 		if (inode && inode == target->mapping->host)
 		if (inode && inode == target->mapping->host)
 			return true;
 			return true;
-		if (page && page == target)
-			return true;
 		if (ino && ino == ino_of_node(target))
 		if (ino && ino == ino_of_node(target))
 			return true;
 			return true;
 	}
 	}
@@ -275,22 +276,21 @@ static bool __has_merged_page(struct f2fs_bio_info *io, struct inode *inode,
 }
 }
 
 
 static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
 static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
-						struct page *page, nid_t ino,
-						enum page_type type)
+				nid_t ino, pgoff_t idx, enum page_type type)
 {
 {
 	enum page_type btype = PAGE_TYPE_OF_BIO(type);
 	enum page_type btype = PAGE_TYPE_OF_BIO(type);
 	struct f2fs_bio_info *io = &sbi->write_io[btype];
 	struct f2fs_bio_info *io = &sbi->write_io[btype];
 	bool ret;
 	bool ret;
 
 
 	down_read(&io->io_rwsem);
 	down_read(&io->io_rwsem);
-	ret = __has_merged_page(io, inode, page, ino);
+	ret = __has_merged_page(io, inode, ino, idx);
 	up_read(&io->io_rwsem);
 	up_read(&io->io_rwsem);
 	return ret;
 	return ret;
 }
 }
 
 
 static void __f2fs_submit_merged_bio(struct f2fs_sb_info *sbi,
 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)
+				struct inode *inode, nid_t ino, pgoff_t idx,
+				enum page_type type, int rw)
 {
 {
 	enum page_type btype = PAGE_TYPE_OF_BIO(type);
 	enum page_type btype = PAGE_TYPE_OF_BIO(type);
 	struct f2fs_bio_info *io;
 	struct f2fs_bio_info *io;
@@ -299,7 +299,7 @@ static void __f2fs_submit_merged_bio(struct f2fs_sb_info *sbi,
 
 
 	down_write(&io->io_rwsem);
 	down_write(&io->io_rwsem);
 
 
-	if (!__has_merged_page(io, inode, page, ino))
+	if (!__has_merged_page(io, inode, ino, idx))
 		goto out;
 		goto out;
 
 
 	/* change META to META_FLUSH in the checkpoint procedure */
 	/* change META to META_FLUSH in the checkpoint procedure */
@@ -318,15 +318,15 @@ out:
 void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, enum page_type type,
 void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, enum page_type type,
 									int rw)
 									int rw)
 {
 {
-	__f2fs_submit_merged_bio(sbi, NULL, NULL, 0, type, rw);
+	__f2fs_submit_merged_bio(sbi, NULL, 0, 0, type, rw);
 }
 }
 
 
 void f2fs_submit_merged_bio_cond(struct f2fs_sb_info *sbi,
 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)
+				struct inode *inode, nid_t ino, pgoff_t idx,
+				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);
+	if (has_merged_page(sbi, inode, ino, idx, type))
+		__f2fs_submit_merged_bio(sbi, inode, ino, idx, type, rw);
 }
 }
 
 
 void f2fs_flush_merged_bios(struct f2fs_sb_info *sbi)
 void f2fs_flush_merged_bios(struct f2fs_sb_info *sbi)
@@ -1432,7 +1432,8 @@ out:
 		ClearPageUptodate(page);
 		ClearPageUptodate(page);
 
 
 	if (wbc->for_reclaim) {
 	if (wbc->for_reclaim) {
-		f2fs_submit_merged_bio_cond(sbi, NULL, page, 0, DATA, WRITE);
+		f2fs_submit_merged_bio_cond(sbi, inode, 0, page->index,
+						DATA, WRITE);
 		remove_dirty_inode(inode);
 		remove_dirty_inode(inode);
 		submitted = NULL;
 		submitted = NULL;
 	}
 	}
@@ -1480,10 +1481,10 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
 	pgoff_t index;
 	pgoff_t index;
 	pgoff_t end;		/* Inclusive */
 	pgoff_t end;		/* Inclusive */
 	pgoff_t done_index;
 	pgoff_t done_index;
+	pgoff_t last_idx = ULONG_MAX;
 	int cycled;
 	int cycled;
 	int range_whole = 0;
 	int range_whole = 0;
 	int tag;
 	int tag;
-	int nwritten = 0;
 
 
 	pagevec_init(&pvec, 0);
 	pagevec_init(&pvec, 0);
 
 
@@ -1569,7 +1570,7 @@ continue_unlock:
 				done = 1;
 				done = 1;
 				break;
 				break;
 			} else if (submitted) {
 			} else if (submitted) {
-				nwritten++;
+				last_idx = page->index;
 			}
 			}
 
 
 			if (--wbc->nr_to_write <= 0 &&
 			if (--wbc->nr_to_write <= 0 &&
@@ -1591,9 +1592,9 @@ continue_unlock:
 	if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
 	if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
 		mapping->writeback_index = done_index;
 		mapping->writeback_index = done_index;
 
 
-	if (nwritten)
+	if (last_idx != ULONG_MAX)
 		f2fs_submit_merged_bio_cond(F2FS_M_SB(mapping), mapping->host,
 		f2fs_submit_merged_bio_cond(F2FS_M_SB(mapping), mapping->host,
-							NULL, 0, DATA, WRITE);
+						0, last_idx, DATA, WRITE);
 
 
 	return ret;
 	return ret;
 }
 }

+ 2 - 2
fs/f2fs/f2fs.h

@@ -2233,8 +2233,8 @@ void destroy_checkpoint_caches(void);
 void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, enum page_type type,
 void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, enum page_type type,
 			int rw);
 			int rw);
 void f2fs_submit_merged_bio_cond(struct f2fs_sb_info *sbi,
 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);
+				struct inode *inode, nid_t ino, pgoff_t idx,
+				enum page_type type, int rw);
 void f2fs_flush_merged_bios(struct f2fs_sb_info *sbi);
 void f2fs_flush_merged_bios(struct f2fs_sb_info *sbi);
 int f2fs_submit_page_bio(struct f2fs_io_info *fio);
 int f2fs_submit_page_bio(struct f2fs_io_info *fio);
 int f2fs_submit_page_mbio(struct f2fs_io_info *fio);
 int f2fs_submit_page_mbio(struct f2fs_io_info *fio);

+ 7 - 5
fs/f2fs/node.c

@@ -1374,7 +1374,8 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
 	up_read(&sbi->node_write);
 	up_read(&sbi->node_write);
 
 
 	if (wbc->for_reclaim) {
 	if (wbc->for_reclaim) {
-		f2fs_submit_merged_bio_cond(sbi, NULL, page, 0, NODE, WRITE);
+		f2fs_submit_merged_bio_cond(sbi, page->mapping->host, 0,
+						page->index, NODE, WRITE);
 		submitted = NULL;
 		submitted = NULL;
 	}
 	}
 
 
@@ -1404,12 +1405,12 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
 			struct writeback_control *wbc, bool atomic)
 			struct writeback_control *wbc, bool atomic)
 {
 {
 	pgoff_t index, end;
 	pgoff_t index, end;
+	pgoff_t last_idx = ULONG_MAX;
 	struct pagevec pvec;
 	struct pagevec pvec;
 	int ret = 0;
 	int ret = 0;
 	struct page *last_page = NULL;
 	struct page *last_page = NULL;
 	bool marked = false;
 	bool marked = false;
 	nid_t ino = inode->i_ino;
 	nid_t ino = inode->i_ino;
-	int nwritten = 0;
 
 
 	if (atomic) {
 	if (atomic) {
 		last_page = last_fsync_dnode(sbi, ino);
 		last_page = last_fsync_dnode(sbi, ino);
@@ -1488,7 +1489,7 @@ continue_unlock:
 				f2fs_put_page(last_page, 0);
 				f2fs_put_page(last_page, 0);
 				break;
 				break;
 			} else if (submitted) {
 			} else if (submitted) {
-				nwritten++;
+				last_idx = page->index;
 			}
 			}
 
 
 			if (page == last_page) {
 			if (page == last_page) {
@@ -1514,8 +1515,9 @@ continue_unlock:
 		goto retry;
 		goto retry;
 	}
 	}
 out:
 out:
-	if (nwritten)
-		f2fs_submit_merged_bio_cond(sbi, NULL, NULL, ino, NODE, WRITE);
+	if (last_idx != ULONG_MAX)
+		f2fs_submit_merged_bio_cond(sbi, NULL, ino, last_idx,
+							NODE, WRITE);
 	return ret ? -EIO: 0;
 	return ret ? -EIO: 0;
 }
 }
 
 

+ 7 - 6
fs/f2fs/segment.c

@@ -263,7 +263,7 @@ static int __commit_inmem_pages(struct inode *inode,
 		.op_flags = REQ_SYNC | REQ_PRIO,
 		.op_flags = REQ_SYNC | REQ_PRIO,
 		.encrypted_page = NULL,
 		.encrypted_page = NULL,
 	};
 	};
-	bool submit_bio = false;
+	pgoff_t last_idx = ULONG_MAX;
 	int err = 0;
 	int err = 0;
 
 
 	list_for_each_entry_safe(cur, tmp, &fi->inmem_pages, list) {
 	list_for_each_entry_safe(cur, tmp, &fi->inmem_pages, list) {
@@ -289,15 +289,15 @@ static int __commit_inmem_pages(struct inode *inode,
 
 
 			/* record old blkaddr for revoking */
 			/* record old blkaddr for revoking */
 			cur->old_addr = fio.old_blkaddr;
 			cur->old_addr = fio.old_blkaddr;
-
-			submit_bio = true;
+			last_idx = page->index;
 		}
 		}
 		unlock_page(page);
 		unlock_page(page);
 		list_move_tail(&cur->list, revoke_list);
 		list_move_tail(&cur->list, revoke_list);
 	}
 	}
 
 
-	if (submit_bio)
-		f2fs_submit_merged_bio_cond(sbi, inode, NULL, 0, DATA, WRITE);
+	if (last_idx != ULONG_MAX)
+		f2fs_submit_merged_bio_cond(sbi, inode, 0, last_idx,
+							DATA, WRITE);
 
 
 	if (!err)
 	if (!err)
 		__revoke_inmem_pages(inode, revoke_list, false, false);
 		__revoke_inmem_pages(inode, revoke_list, false, false);
@@ -1932,7 +1932,8 @@ void f2fs_wait_on_page_writeback(struct page *page,
 	if (PageWriteback(page)) {
 	if (PageWriteback(page)) {
 		struct f2fs_sb_info *sbi = F2FS_P_SB(page);
 		struct f2fs_sb_info *sbi = F2FS_P_SB(page);
 
 
-		f2fs_submit_merged_bio_cond(sbi, NULL, page, 0, type, WRITE);
+		f2fs_submit_merged_bio_cond(sbi, page->mapping->host,
+						0, page->index, type, WRITE);
 		if (ordered)
 		if (ordered)
 			wait_on_page_writeback(page);
 			wait_on_page_writeback(page);
 		else
 		else