[Devel] [PATCH RHEL7 COMMIT] ploop: Read 10 BAT clusters on holes_bitmap population

Konstantin Khorenko khorenko at virtuozzo.com
Wed Feb 5 12:55:18 MSK 2020


The commit is pushed to "branch-rh7-3.10.0-1062.7.1.vz7.130.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1062.7.1.vz7.130.15
------>
commit c1ce7a9def75a92300acaae269f0cfeba6200035
Author: Kirill Tkhai <ktkhai at virtuozzo.com>
Date:   Wed Feb 5 12:55:18 2020 +0300

    ploop: Read 10 BAT clusters on holes_bitmap population
    
    This makes a batch and improves performance or BAT analyzing.
    Now we submit up to 10 clusters at read and before wait of
    request completion.
    
    Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
    
    Patchset description:
    Possibility to batch page reads and batch on holes_bitmap population
    
    Submit batch request up to 10 clusters (10Mb, 2560 pages)
    during holes_bitmap population to speed up ploop mount
    of big images.
    
    https://jira.sw.ru/browse/PSBM-101246
    
    Kirill Tkhai (4):
          ploop: Teach dio_sync_io() work with many pages
          ploop: Teach kaio_sync_io() work with many pages
          ploop: Introduce .sync_read_many method
          ploop: Read 10 BAT clusters on holes_bitmap population
---
 drivers/block/ploop/fmt_ploop1.c | 86 +++++++++++++++++++++++++---------------
 1 file changed, 55 insertions(+), 31 deletions(-)

diff --git a/drivers/block/ploop/fmt_ploop1.c b/drivers/block/ploop/fmt_ploop1.c
index 6745d29e53096..806f020f0bb7d 100644
--- a/drivers/block/ploop/fmt_ploop1.c
+++ b/drivers/block/ploop/fmt_ploop1.c
@@ -140,13 +140,36 @@ ploop1_compose(struct ploop_delta * delta, int nchunks, struct ploop_ctl_chunk *
 	return ploop_io_init(delta, nchunks, pc);
 }
 
+static unsigned int parse_bat_page_for_hb(struct ploop_delta *delta,
+					  struct ploop1_private *ph,
+					  struct page *page,
+					  unsigned int block)
+{
+	unsigned int i, off = block ? 0 : PLOOP_MAP_OFFSET;
+	u32 *index;
+
+	index = page_address(page);
+	for (i = off; i < INDEX_PER_PAGE && block + i - off < ph->nr_bat_entries; i++) {
+		if (index[i] != 0) {
+			unsigned int cluster = index[i] >> ploop_map_log(delta->plo);
+			/*
+			 * On grow cluster above nr_clusters_in_bitmap may
+			 * be assigned. Ignore it.
+			 */
+			if (likely(cluster < ph->nr_clusters_in_bitmap))
+				ploop_clear_holes_bitmap_bit(cluster, delta);
+		}
+	}
+
+	return i - off;
+}
+
 static int populate_holes_bitmap(struct ploop_delta *delta,
 				 struct ploop1_private *ph)
 {
-	unsigned int block, nr_blocks, size, off, md_off;
-	struct page *page;
+	unsigned int block, nr_blocks, md_off, count, nr_all_pages, size, consumed = 0;
+	struct page **pages;
 	sector_t sec;
-	u32 *index;
 	int i, ret;
 
 	if (test_bit(PLOOP_S_NO_FALLOC_DISCARD, &delta->plo->state))
@@ -159,10 +182,18 @@ static int populate_holes_bitmap(struct ploop_delta *delta,
 	}
 
 	ret = -ENOMEM;
-	page = alloc_page(GFP_KERNEL);
-	if (!page)
+	/* Use multiplier 10 for bigger batch and better performance */
+	nr_all_pages = 10 * cluster_size_in_bytes(delta->plo) / PAGE_SIZE;
+	pages = kvzalloc(sizeof(struct page *) * nr_all_pages, GFP_KERNEL);
+	if (!pages)
 		return ret;
 
+	for (i = 0; i < nr_all_pages; i++) {
+		pages[i] = alloc_page(GFP_KERNEL);
+		if (!pages[i])
+			goto out;
+	}
+
 	/*
 	 * Holes bitmap is map of clusters from start of file to maximum
 	 * cluster, which may be refered by BAT.
@@ -177,7 +208,7 @@ static int populate_holes_bitmap(struct ploop_delta *delta,
 
 	delta->holes_bitmap = kvmalloc(size, GFP_KERNEL);
 	if (!delta->holes_bitmap)
-		goto put_page;
+		goto out;
 	ph->nr_clusters_in_bitmap = nr_blocks;
 	memset(delta->holes_bitmap, 0xff, size);
 	/* Tail clusters are not available for allocation */
@@ -188,44 +219,37 @@ static int populate_holes_bitmap(struct ploop_delta *delta,
 		clear_bit(i, delta->holes_bitmap);
 
 	block = 0;
-	while (block < nr_blocks) {
+	while (block < ph->nr_bat_entries) {
 		if (!ploop1_map_index(delta, block, &sec)) {
 			/*
 			 * BAT area can address wider region, than disk size.
 			 * This may be a result of shrinking large disk
 			 * to a small size.
 			 */
-			pr_info("ploop%u: bat is bigger than disk size\n",
+			pr_err("ploop%u: bat is bigger than disk size\n",
 				delta->plo->index);
-			goto put_page;
+			goto out;
 		}
-		ret = delta->io.ops->sync_read(&delta->io, page,
-					       4096, 0, sec);
-		if (ret)
-			goto put_page;
-
-		off = block ? 0 : PLOOP_MAP_OFFSET;
-
-		index = page_address(page);
-		for (i = off; i < INDEX_PER_PAGE && block + i - off < nr_blocks; i++) {
-			if (index[i] != 0) {
-				unsigned int cluster = index[i] >> ploop_map_log(delta->plo);
-				/*
-				 * On grow cluster above nr_clusters_in_bitmap may
-				 * be assigned. Ignore it.
-				 */
-				if (likely(cluster < ph->nr_clusters_in_bitmap))
-					ploop_clear_holes_bitmap_bit(cluster, delta);
-			}
+		/* Images with big BAT and small data may be shorter than nr_all_pages */
+		count = min_t(unsigned int, nr_all_pages,
+				(ph->l1_off << 9) / PAGE_SIZE - consumed);
+		ret = delta->io.ops->sync_read_many(&delta->io, pages, count, sec);
+		if (ret) {
+			pr_err("ploop: too short BAT\n");
+			goto out;
 		}
 
-		block += (block ? INDEX_PER_PAGE : INDEX_PER_PAGE - PLOOP_MAP_OFFSET);
+		for (i = 0; i < count && block < ph->nr_bat_entries; i++)
+			block += parse_bat_page_for_hb(delta, ph, pages[i], block);
+		consumed += count;
 	}
 
 	ret = 0;
-
-put_page:
-	put_page(page);
+out:
+	for (i = 0; i < nr_all_pages; i++)
+		if (pages[i])
+			put_page(pages[i]);
+	kvfree(pages);
 	return ret;
 }
 


More information about the Devel mailing list