[Devel] [PATCH VZ9 4/5] dm-qcow2: add merge_backward set_eventfd command

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Fri Feb 28 07:21:07 MSK 2025


This eventfd can be used to get an event when merge_backward start work
have finished and is waiting for completion.

Note: The eventfd can be changed even while work is running.

Locking:

The backward_merge.eventfd_ctx is protected from being released by
tgt->ctl_mutex.

https://virtuozzo.atlassian.net/browse/VSTOR-100466
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 drivers/md/dm-qcow2-cmd.c | 37 ++++++++++++++++++++++++++++++++++++-
 drivers/md/dm-qcow2.h     |  2 ++
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/md/dm-qcow2-cmd.c b/drivers/md/dm-qcow2-cmd.c
index b758e1c05c749..2959a8ffe8d49 100644
--- a/drivers/md/dm-qcow2-cmd.c
+++ b/drivers/md/dm-qcow2-cmd.c
@@ -5,6 +5,8 @@
 #include <linux/device-mapper.h>
 #include <linux/sched/signal.h>
 #include <linux/file.h>
+#include <linux/eventfd.h>
+#include <linux/minmax.h>
 #include <linux/error-injection.h>
 #include "dm-qcow2.h"
 
@@ -248,6 +250,8 @@ void qcow2_merge_backward_work(struct work_struct *work)
 	} else {
 		/* Finish merge */
 		tgt->backward_merge.state = BACKWARD_MERGE_WAIT_COMPLETION;
+		if (tgt->backward_merge.eventfd_ctx)
+			eventfd_signal(tgt->backward_merge.eventfd_ctx, 1);
 	}
 	mutex_unlock(&tgt->ctl_mutex);
 }
@@ -310,6 +314,24 @@ static bool qcow2_backward_merge_should_stop(struct qcow2_target *tgt)
 	return READ_ONCE(tgt->backward_merge.state) == BACKWARD_MERGE_STOP;
 }
 
+#define QCOW2_FILE_UNBIND -1
+
+static int qcow2_merge_backward_set_eventfd(struct qcow2_target *tgt, int efd)
+{
+	struct eventfd_ctx *ctx = NULL;
+
+	ctx = efd == QCOW2_FILE_UNBIND ? NULL : eventfd_ctx_fdget(efd);
+	if (IS_ERR(ctx))
+		return PTR_ERR(ctx);
+
+	mutex_lock(&tgt->ctl_mutex);
+	swap(ctx, tgt->backward_merge.eventfd_ctx);
+	if (ctx)
+		eventfd_ctx_put(ctx);
+	mutex_unlock(&tgt->ctl_mutex);
+	return 0;
+}
+
 static struct qcow2 *qcow2_get_img(struct qcow2_target *tgt, u32 img_id, u8 *ref_index)
 {
 	struct qcow2 *qcow2;
@@ -468,14 +490,27 @@ int qcow2_message(struct dm_target *ti, unsigned int argc, char **argv,
 		ret = qcow2_get_event(tgt, result, maxlen);
 		goto out;
 	} else if (!strcmp(argv[0], "merge_backward")) {
-		if (argc != 2) {
+		if (argc < 2) {
 			ret = -EINVAL;
 			goto out;
 		}
 		if (!strcmp(argv[1], "cancel")) {
+			if (argc != 2) {
+				ret = -EINVAL;
+				goto out;
+			}
 			qcow2_merge_backward_cancel(tgt);
 			ret = 0;
 			goto out;
+		} else if (!strcmp(argv[1], "set_eventfd")) {
+			int efd;
+
+			if (argc != 3 || kstrtoint(argv[2], 10, &efd)) {
+				ret = -EINVAL;
+				goto out;
+			}
+			ret = qcow2_merge_backward_set_eventfd(tgt, efd);
+			goto out;
 		}
 	}
 
diff --git a/drivers/md/dm-qcow2.h b/drivers/md/dm-qcow2.h
index b54fbeb5bac11..f95914190c8bb 100644
--- a/drivers/md/dm-qcow2.h
+++ b/drivers/md/dm-qcow2.h
@@ -5,6 +5,7 @@
 #include <linux/percpu-refcount.h>
 #include <linux/device-mapper.h>
 #include <linux/fs.h>
+#include <linux/eventfd.h>
 #include "dm-core.h"
 
 #define DM_MSG_PREFIX "qcow2"
@@ -119,6 +120,7 @@ struct qcow2_backward_merge {
 	struct work_struct work;
 	enum qcow2_backward_merge_state state;
 	int error;
+	struct eventfd_ctx *eventfd_ctx;
 };
 
 struct qcow2_target {
-- 
2.48.1



More information about the Devel mailing list