[PATCH] block : add larger order folio size instead of pages

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When mTHP is enabled, IO can contain larger folios instead of pages.
In such cases add a larger size to the bio instead of looping through
pages. This reduces the overhead of iterating through pages for larger
block sizes. perf diff before and after this change:

Perf diff for write I/O with 128K block size:
	1.22%     -0.97%  [kernel.kallsyms]  [k] bio_iov_iter_get_pages
Perf diff for read I/O with 128K block size:
	4.13%     -3.26%  [kernel.kallsyms]  [k] bio_iov_iter_get_pages

Signed-off-by: Kundan Kumar <kundan.kumar@xxxxxxxxxxx>
---
 block/bio.c | 37 ++++++++++++++++++++++++++++---------
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index 38baedb39c6f..c507e47e3c46 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1247,8 +1247,10 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
 	struct page **pages = (struct page **)bv;
 	ssize_t size, left;
 	unsigned len, i = 0;
-	size_t offset;
+	size_t offset, folio_offset, size_folio;
 	int ret = 0;
+	unsigned short num_pages;
+	struct folio *folio;
 
 	/*
 	 * Move page array up in the allocated memory for the bio vecs as far as
@@ -1289,16 +1291,33 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
 
 	for (left = size, i = 0; left > 0; left -= len, i++) {
 		struct page *page = pages[i];
+		folio = page_folio(page);
+
+		if (!folio_test_large(folio) ||
+		   (bio_op(bio) == REQ_OP_ZONE_APPEND)) {
+			len = min_t(size_t, PAGE_SIZE - offset, left);
+			if (bio_op(bio) == REQ_OP_ZONE_APPEND) {
+				ret = bio_iov_add_zone_append_page(bio, page,
+						len, offset);
+				if (ret)
+					break;
+			} else
+				bio_iov_add_page(bio, page, len, offset);
+		} else {
+			/* See the offset of folio and the size */
+			folio_offset = (folio_page_idx(folio, page)
+					<< PAGE_SHIFT) + offset;
+			size_folio = folio_size(folio);
 
-		len = min_t(size_t, PAGE_SIZE - offset, left);
-		if (bio_op(bio) == REQ_OP_ZONE_APPEND) {
-			ret = bio_iov_add_zone_append_page(bio, page, len,
-					offset);
-			if (ret)
-				break;
-		} else
-			bio_iov_add_page(bio, page, len, offset);
+			/* Calculate the length of folio to be added */
+			len = min_t(size_t, (size_folio - folio_offset), left);
+
+			num_pages = DIV_ROUND_UP(offset + len, PAGE_SIZE);
 
+			bio_iov_add_page(bio, page, len, offset);
+			/* Skip the pages which got added */
+			i = i + (num_pages - 1);
+		}
 		offset = 0;
 	}
 
-- 
2.25.1





[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux