[Devel] [PATCH vz9] dm-ploop: issue sync from proper context

Alexander Atanasov alexander.atanasov at virtuozzo.com
Thu Jan 30 11:04:22 MSK 2025


ploop did vfs_sync(...) from interrupt context which is wrong.
It worked for xfs/ext4 due to the request is offloaded to
journaling which runs in different threads.

Fix this by offloading sync and respective pio endio to some
of the worker threads

https://virtuozzo.atlassian.net/browse/VSTOR-98792
Signed-off-by: Alexander Atanasov <alexander.atanasov at virtuozzo.com>
---
 drivers/md/dm-ploop-map.c | 38 ++++++++++++++++++++++++++++++++++----
 drivers/md/dm-ploop.h     |  3 ++-
 2 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
index 7efbaedd69e0..f6fc453f7464 100644
--- a/drivers/md/dm-ploop-map.c
+++ b/drivers/md/dm-ploop-map.c
@@ -21,6 +21,7 @@
 #include "dm-rq.h"
 
 static inline int ploop_runners_add_work(struct ploop *ploop, struct pio *pio);
+static inline int ploop_runners_add_work_offload(struct ploop *ploop, struct pio *pio);
 static void ploop_bat_write_complete(struct pio *pio, void *piwb_ptr,
 				     blk_status_t bi_status);
 
@@ -213,6 +214,21 @@ static void ploop_prq_endio(struct pio *pio, void *prq_ptr,
 	dm_complete_request(rq, bi_status);
 }
 
+static void ploop_wrkr_pio_endio(struct pio *pio)
+{
+	ploop_endio_t endio_cb = pio->endio_cb;
+	void *endio_cb_data = pio->endio_cb_data;
+	bool free_on_endio = pio->free_on_endio;
+	struct file *file;
+
+	file = ploop_top_delta(pio->ploop)->file;
+	vfs_fsync(file, 1);
+	endio_cb(pio, endio_cb_data, pio->bi_status);
+	if (free_on_endio) {
+		ploop_free_pio(pio->ploop, pio);
+	}
+}
+
 static void ploop_do_pio_endio(struct pio *pio)
 {
 	ploop_endio_t endio_cb = pio->endio_cb;
@@ -224,10 +240,9 @@ static void ploop_do_pio_endio(struct pio *pio)
 
 	/* REQ_FUA requires us to flush all before pio is completed */
 	if (pio->bi_op & REQ_FUA) {
-		struct file *file;
-
-		file = ploop_top_delta(pio->ploop)->file;
-		vfs_fsync(file, 1);
+		pio->queue_list_id = PLOOP_LIST_ENDPIO;
+		ploop_runners_add_work_offload(pio->ploop, pio);
+		return;
 	}
 
 	endio_cb(pio, endio_cb_data, pio->bi_status);
@@ -2129,6 +2144,18 @@ static inline int ploop_runners_add_work(struct ploop *ploop, struct pio *pio)
 	return 0;
 }
 
+static inline int ploop_runners_add_work_offload(struct ploop *ploop, struct pio *pio)
+{
+	struct ploop_worker *wrkr;
+
+	wrkr = READ_ONCE(ploop->last_used_runner)->next;
+	WRITE_ONCE(ploop->last_used_runner, wrkr);
+	llist_add((struct llist_node *)(&pio->list), &wrkr->work_llist);
+	wake_up_process(wrkr->task);
+
+	return 0;
+}
+
 static inline int ploop_runners_add_work_list(struct ploop *ploop, struct llist_node *list)
 {
 	struct llist_node *pos, *t;
@@ -2346,6 +2373,9 @@ int ploop_pio_runner(void *data)
 			case PLOOP_LIST_WRITEBACK: /* Write back pio */
 				ploop_submit_rw_mapped(ploop, pio);
 				break;
+			case PLOOP_LIST_ENDPIO:
+				ploop_wrkr_pio_endio(pio);
+				continue;
 			default:
 				WARN_ON_ONCE(1);
 			}
diff --git a/drivers/md/dm-ploop.h b/drivers/md/dm-ploop.h
index 43e65e841e4a..06d95c525c90 100644
--- a/drivers/md/dm-ploop.h
+++ b/drivers/md/dm-ploop.h
@@ -145,6 +145,7 @@ enum {
 	/* Following to be used as a list id only */
 	PLOOP_LIST_WRITEBACK,
 	PLOOP_LIST_FLUSHPIO,
+	PLOOP_LIST_ENDPIO,
 };
 
 struct ploop_worker {
@@ -310,7 +311,7 @@ struct pio {
 #define PLOOP_REF_INDEX_INVALID	2
 	unsigned int ref_index:2;
 
-	u8 queue_list_id:3; /* id in ploop->pios */
+	u8 queue_list_id; /* id in ploop->pios */
 
 	struct ploop_index_wb *piwb;
 
-- 
2.43.0



More information about the Devel mailing list