[Devel] [PATCH vz9 v1 23/63] dm-ploop: add delay for metadata writeback

Alexander Atanasov alexander.atanasov at virtuozzo.com
Fri Jan 24 18:35:57 MSK 2025


From: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>

Revert llist conversion for metadata writeback.
Create new list for priority metadata updates, which are triggered
by FUA requests.
Write metadata for all other requests in batch after some delay.
Add new parameter to specify delay time.
Always submit COW and discard io to prio list.

https://virtuozzo.atlassian.net/browse/VSTOR-91817
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>
---
 drivers/md/dm-ploop-bat.c    |  2 ++
 drivers/md/dm-ploop-map.c    | 66 ++++++++++++++++++++++++++++++------
 drivers/md/dm-ploop-target.c | 13 +++++++
 drivers/md/dm-ploop.h        | 10 +++++-
 4 files changed, 80 insertions(+), 11 deletions(-)

diff --git a/drivers/md/dm-ploop-bat.c b/drivers/md/dm-ploop-bat.c
index 96ba099b1ca4..33069d580e87 100644
--- a/drivers/md/dm-ploop-bat.c
+++ b/drivers/md/dm-ploop-bat.c
@@ -88,7 +88,9 @@ static struct md_page *ploop_alloc_md_page(u32 id)
 	md->page = page;
 	md->kmpage = kmap(page);
 	md->id = id;
+	md->high_prio = false;
 	spin_lock_init(&md->md_lock);
+
 	return md;
 err_page:
 	kfree(levels);
diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
index c6e39cec1134..92844d032810 100644
--- a/drivers/md/dm-ploop-map.c
+++ b/drivers/md/dm-ploop-map.c
@@ -553,17 +553,39 @@ static void ploop_unlink_completed_pio(struct ploop *ploop, struct pio *pio)
 
 static bool ploop_md_make_dirty(struct ploop *ploop, struct md_page *md)
 {
+	unsigned long flags;
 	bool new = false;
 
+	write_lock_irqsave(&ploop->bat_rwlock, flags);
 	WARN_ON_ONCE(test_bit(MD_WRITEBACK, &md->status));
 	if (!test_and_set_bit(MD_DIRTY, &md->status)) {
-		llist_add(&md->wb_llink, &ploop->wb_batch_llist);
+		list_add(&md->wb_link, &ploop->wb_batch_list);
 		new = true;
 	}
-
+	write_unlock_irqrestore(&ploop->bat_rwlock, flags);
 	return new;
 }
 
+static void ploop_md_up_prio(struct ploop *ploop, struct md_page *md)
+{
+	unsigned long flags;
+
+	write_lock_irqsave(&ploop->bat_rwlock, flags);
+	if (test_bit(MD_WRITEBACK, &md->status))
+		goto out;
+	if (md->high_prio)
+		goto out;
+
+	md->high_prio = true;
+	WARN_ON_ONCE(!test_bit(MD_DIRTY, &md->status));
+
+	list_del(&md->wb_link);
+	list_add(&md->wb_link, &ploop->wb_batch_list_prio);
+
+out:
+	write_unlock_irqrestore(&ploop->bat_rwlock, flags);
+}
+
 static bool ploop_pio_endio_if_all_zeros(struct pio *pio)
 {
 	struct bvec_iter bi = {
@@ -1421,6 +1443,8 @@ static void ploop_submit_cow_index_wb(struct ploop_cow *cow)
 	WRITE_ONCE(md->bat_levels[clu], ploop_top_level(ploop));
 	spin_unlock_irqrestore(&md->md_lock, flags);
 
+	ploop_md_up_prio(ploop, md);
+
 	/* Prevent double clearing of holes_bitmap bit on complete_cow() */
 	cow->dst_clu = BAT_ENTRY_NONE;
 	spin_lock_irq(&ploop->deferred_lock);
@@ -1518,6 +1542,7 @@ static bool ploop_locate_new_cluster_and_attach_pio(struct ploop *ploop,
 	if (pio->bi_op & REQ_FUA) {
 		piwb->pio->bi_op |= REQ_FUA;
 		ploop_attach_end_action(pio, piwb);
+		ploop_md_up_prio(ploop, md);
 	}
 
 	attached = true;
@@ -1762,6 +1787,7 @@ static void ploop_process_one_discard_pio(struct ploop *ploop, struct pio *pio)
 
 	if (bat_update_prepared)
 		ploop_md_make_dirty(ploop, md);
+	ploop_md_up_prio(ploop, md);
 out:
 	return;
 err:
@@ -1797,25 +1823,45 @@ static void ploop_process_resubmit_pios(struct ploop *ploop,
 	}
 }
 
-static void ploop_submit_metadata_writeback(struct ploop *ploop)
+static void ploop_submit_metadata_writeback_from_list(struct ploop *ploop,
+						      struct list_head *list)
 {
 	struct md_page *md;
-	struct md_page *t;
-	struct llist_node *wbl;
 
-	wbl = llist_del_all(&ploop->wb_batch_llist);
-	if (!wbl)
-		return;
-	wbl = llist_reverse_order(wbl);
-	llist_for_each_entry_safe(md, t, wbl, wb_llink) {
+	while (1) {
+		write_lock_irq(&ploop->bat_rwlock);
+		md = list_first_entry_or_null(list, struct md_page, wb_link);
+		if (!md) {
+			write_unlock_irq(&ploop->bat_rwlock);
+			break;
+		}
+		list_del_init(&md->wb_link);
+		/* L1L2 mustn't be redirtyed, when wb in-flight! */
+
 		WARN_ON_ONCE(!test_bit(MD_DIRTY, &md->status));
 		WARN_ON_ONCE(test_bit(MD_WRITEBACK, &md->status));
 		set_bit(MD_WRITEBACK, &md->status);
 		clear_bit(MD_DIRTY, &md->status);
+		md->high_prio = false;
+		write_unlock_irq(&ploop->bat_rwlock);
+
 		ploop_index_wb_submit(ploop, md->piwb);
 	}
 }
 
+static void ploop_submit_metadata_writeback(struct ploop *ploop)
+{
+	ktime_t time;
+
+	ploop_submit_metadata_writeback_from_list(ploop, &ploop->wb_batch_list_prio);
+
+	time = ktime_get();
+	if (ktime_after(time, ktime_add_ms(ploop->last_md_submit, ploop->md_submit_delay_ms))) {
+		ploop->last_md_submit = time;
+		ploop_submit_metadata_writeback_from_list(ploop, &ploop->wb_batch_list);
+	}
+}
+
 static void process_ploop_fsync_work(struct ploop *ploop, struct llist_node *llflush_pios)
 {
 	struct file *file;
diff --git a/drivers/md/dm-ploop-target.c b/drivers/md/dm-ploop-target.c
index 00d160b3fd3c..f714c2cb540f 100644
--- a/drivers/md/dm-ploop-target.c
+++ b/drivers/md/dm-ploop-target.c
@@ -422,6 +422,11 @@ static int ploop_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
 	INIT_LIST_HEAD(&ploop->cluster_lk_list);
 	init_llist_head(&ploop->wb_batch_llist);
+	INIT_LIST_HEAD(&ploop->wb_batch_list);
+	INIT_LIST_HEAD(&ploop->wb_batch_list_prio);
+	ploop->last_md_submit = 0;
+	ploop->md_submit_delay_ms = PLOOP_DEFAULT_METADATA_SUBMIT_DELAY;
+
 	ploop->bat_entries = RB_ROOT;
 	timer_setup(&ploop->enospc_timer, ploop_enospc_timer, 0);
 
@@ -503,6 +508,14 @@ static int ploop_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 			EAT_ARG(argc, argv);
 			continue;
 		}
+#define PLOOP_MD_DELAY_ARG "metadata_delay="
+		if (strncmp(argv[0], PLOOP_MD_DELAY_ARG, sizeof(PLOOP_MD_DELAY_ARG) - 1) == 0) {
+			if (kstrtou64(argv[0] + sizeof(PLOOP_MD_DELAY_ARG) - 1, 10,
+			    &ploop->md_submit_delay_ms) < 0)
+				goto err;
+			EAT_ARG(argc, argv);
+			continue;
+		}
 		break;
 	}
 
diff --git a/drivers/md/dm-ploop.h b/drivers/md/dm-ploop.h
index 7355b3fbcc9a..8bfc5e87a24e 100644
--- a/drivers/md/dm-ploop.h
+++ b/drivers/md/dm-ploop.h
@@ -122,10 +122,12 @@ struct md_page {
 	u8 *bat_levels;
 	struct llist_head wait_llist;
 
-	struct llist_node wb_llink;
+	struct list_head wb_link;
 	struct ploop_index_wb *piwb;
 
 	spinlock_t md_lock;
+
+	bool high_prio;
 };
 
 enum {
@@ -174,6 +176,12 @@ struct ploop {
 	rwlock_t bat_rwlock;
 
 	struct llist_head wb_batch_llist;
+	struct list_head wb_batch_list;
+	struct list_head wb_batch_list_prio;
+
+	ktime_t last_md_submit;
+#define PLOOP_DEFAULT_METADATA_SUBMIT_DELAY 10000
+	uint64_t md_submit_delay_ms;
 
 	/*
 	 * Hash table to link non-exclusive submitted bios.
-- 
2.43.0



More information about the Devel mailing list