[Devel] [PATCH VZ9 3/3] dm-ploop: add delay for metadata writeback

Andrey Zhadchenko andrey.zhadchenko at virtuozzo.com
Fri Sep 27 12:53:36 MSK 2024


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.

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

diff --git a/drivers/md/dm-ploop-bat.c b/drivers/md/dm-ploop-bat.c
index cbe48e376097..dd515251a75d 100644
--- a/drivers/md/dm-ploop-bat.c
+++ b/drivers/md/dm-ploop-bat.c
@@ -88,6 +88,7 @@ static struct md_page *ploop_alloc_md_page(u32 id)
 	md->piwb = NULL;
 	md->page = page;
 	md->id = id;
+	md->high_prio = false;
 	return md;
 err_page:
 	kfree(levels);
diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
index 30321691bfdc..51c645623c4e 100644
--- a/drivers/md/dm-ploop-map.c
+++ b/drivers/md/dm-ploop-map.c
@@ -562,6 +562,26 @@ static bool ploop_md_make_dirty(struct ploop *ploop, struct md_page *md)
 	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 (md->status & MD_WRITEBACK)
+		goto out;
+	if (md->high_prio)
+		goto out;
+
+	md->high_prio = true;
+	WARN_ON_ONCE(!(md->status & MD_DIRTY));
+
+	list_del(&md->wb_link);
+	list_add_tail(&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 = {
@@ -1493,6 +1513,7 @@ static bool ploop_locate_new_cluster_and_attach_pio(struct ploop *ploop,
 	if (pio->bi_op & REQ_FUA) {
 		piwb->is_fua = true;
 		ploop_attach_end_action(pio, piwb);
+		ploop_md_up_prio(ploop, md);
 	}
 	attached = true;
 out:
@@ -1769,14 +1790,13 @@ 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;
 
 	while (1) {
 		write_lock_irq(&ploop->bat_rwlock);
-		md = list_first_entry_or_null(&ploop->wb_batch_list,
-				struct md_page, wb_link);
+		md = list_first_entry_or_null(list, struct md_page, wb_link);
 		if (!md) {
 			write_unlock_irq(&ploop->bat_rwlock);
 			break;
@@ -1787,12 +1807,26 @@ static void ploop_submit_metadata_writeback(struct ploop *ploop)
 			     (md->status & MD_WRITEBACK));
 		md->status |= MD_WRITEBACK;
 		md->status &= ~MD_DIRTY;
+		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);
+	}
+}
+
 void do_ploop_work(struct work_struct *ws)
 {
 	struct ploop *ploop = container_of(ws, struct ploop, worker);
diff --git a/drivers/md/dm-ploop-target.c b/drivers/md/dm-ploop-target.c
index 8b3b840dea66..7024940dc5e9 100644
--- a/drivers/md/dm-ploop-target.c
+++ b/drivers/md/dm-ploop-target.c
@@ -379,6 +379,9 @@ static int ploop_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 	INIT_LIST_HEAD(&ploop->enospc_pios);
 	INIT_LIST_HEAD(&ploop->cluster_lk_list);
 	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);
 
@@ -468,6 +471,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 dcdd3e47535c..9aad5735230c 100644
--- a/drivers/md/dm-ploop.h
+++ b/drivers/md/dm-ploop.h
@@ -124,6 +124,8 @@ struct md_page {
 
 	struct list_head wb_link;
 	struct ploop_index_wb *piwb;
+
+	bool high_prio;
 };
 
 enum {
@@ -167,6 +169,11 @@ struct ploop {
 
 	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.
 	 * This is needed for discard to check, nobody uses
-- 
2.39.3



More information about the Devel mailing list