<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Looks good to me.</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Reviewed-by: Vasileios Almpanis <a style="margin: 0px; text-align: left;" data-linkindex="0" title="mailto:andrey.zhadchenko@virtuozzo.com" class="OWAAutoLink elementToProof" id="LPlnkOWA1e8c1128-feb3-880e-eddd-c9ff60694920" href="mailto:andrey.zhadchenko@virtuozzo.com">
&lt;vasileios.almpanis@virtuozzo.com&gt;</a></div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> devel-bounces@openvz.org &lt;devel-bounces@openvz.org&gt; on behalf of Andrey Zhadchenko &lt;andrey.zhadchenko@virtuozzo.com&gt;<br>
<b>Sent:</b> Monday, September 8, 2025 7:27 PM<br>
<b>To:</b> Konstantin Khorenko &lt;khorenko@virtuozzo.com&gt;; Pavel Tikhomirov &lt;ptikhomirov@virtuozzo.com&gt;<br>
<b>Cc:</b> devel@openvz.org &lt;devel@openvz.org&gt;<br>
<b>Subject:</b> [Devel] [PATCH VZ9] dm-qcow2: allow specifying depth to merge intermediate images</font>
<div>&nbsp;</div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">dm-qcow2 is almost ready to merge intermediate images, thanks<br>
to separated metadata tables and qio being per-qcow2.<br>
So this patch mostly propagates which qcow2 we want to use<br>
instead of tgt-&gt;top.<br>
<br>
qcow2_merge_backward_complete is a bit harder due to in-middle<br>
replacement and needing to recalculate img_id for a part of<br>
image chain.<br>
<br>
<a href="https://virtuozzo.atlassian.net/browse/VSTOR-101375">https://virtuozzo.atlassian.net/browse/VSTOR-101375</a><br>
Signed-off-by: Andrey Zhadchenko &lt;andrey.zhadchenko@virtuozzo.com&gt;<br>
---<br>
&nbsp;drivers/md/dm-qcow2-cmd.c | 82 ++++++++++++++++++++++++++++-----------<br>
&nbsp;drivers/md/dm-qcow2.h&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; 1 +<br>
&nbsp;2 files changed, 61 insertions(+), 22 deletions(-)<br>
<br>
diff --git a/drivers/md/dm-qcow2-cmd.c b/drivers/md/dm-qcow2-cmd.c<br>
index e77052ad61e6b..d59fa82dbffbc 100644<br>
--- a/drivers/md/dm-qcow2-cmd.c<br>
+++ b/drivers/md/dm-qcow2-cmd.c<br>
@@ -116,9 +116,9 @@ static int qcow2_service_iter(struct qcow2_target *tgt, struct qcow2 *qcow2,<br>
&nbsp;}<br>
&nbsp;ALLOW_ERROR_INJECTION(qcow2_service_iter, ERRNO);<br>
&nbsp;<br>
-static int qcow2_merge_common(struct qcow2_target *tgt)<br>
+static int qcow2_merge_common(struct qcow2_target *tgt, struct qcow2 *qcow2)<br>
&nbsp;{<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct qcow2 *qcow2 = tgt-&gt;top, *lower = qcow2-&gt;lower;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct qcow2 *lower = qcow2-&gt;lower;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u32 clu_size = qcow2-&gt;clu_size;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; loff_t end = lower-&gt;hdr.size;<br>
&nbsp;<br>
@@ -139,9 +139,8 @@ static int qcow2_merge_forward(struct qcow2_target *tgt)<br>
&nbsp;}<br>
&nbsp;ALLOW_ERROR_INJECTION(qcow2_merge_forward, ERRNO);<br>
&nbsp;<br>
-static int qcow2_break_l1cow(struct qcow2_target *tgt)<br>
+static int qcow2_break_l1cow(struct qcow2_target *tgt, struct qcow2 *qcow2)<br>
&nbsp;{<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct qcow2 *qcow2 = tgt-&gt;top;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; loff_t end = qcow2-&gt;hdr.size;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; loff_t step = (u64)qcow2-&gt;l2_entries * qcow2-&gt;clu_size;<br>
&nbsp;<br>
@@ -152,25 +151,35 @@ static int qcow2_break_l1cow(struct qcow2_target *tgt)<br>
&nbsp;static void set_backward_merge_in_process(struct qcow2_target *tgt,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct qcow2 *qcow2, bool set)<br>
&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct qcow2 *top = tgt-&gt;top;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LIST_HEAD(list);<br>
&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * There are no writes if it is not the top qcow2 image.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * so we do not need to stop and flush requests when setting<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (qcow2 != top &amp;&amp; set) {<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qcow2-&gt;backward_merge_in_process = set;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
+<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * To avoid race between allocations and COWS<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * we completely stop queueing qios and wait<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * for pending qios. Lock is for visability.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_lock_irq(&amp;qcow2-&gt;deferred_lock);<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qcow2-&gt;pause_submitting_qios = true;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_unlock_irq(&amp;qcow2-&gt;deferred_lock);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_lock_irq(&amp;top-&gt;deferred_lock);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; top-&gt;pause_submitting_qios = true;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_unlock_irq(&amp;top-&gt;deferred_lock);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qcow2_inflight_ref_switch(tgt);<br>
&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* queue is stopped */<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_lock_irq(&amp;qcow2-&gt;deferred_lock);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_lock_irq(&amp;top-&gt;deferred_lock);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WARN_ON_ONCE(qcow2-&gt;backward_merge_in_process == set);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qcow2-&gt;backward_merge_in_process = set;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qcow2-&gt;pause_submitting_qios = false;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list_splice_init(&amp;qcow2-&gt;paused_qios, &amp;list);<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_unlock_irq(&amp;qcow2-&gt;deferred_lock);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; top-&gt;pause_submitting_qios = false;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list_splice_init(&amp;top-&gt;paused_qios, &amp;list);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_unlock_irq(&amp;top-&gt;deferred_lock);<br>
&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qcow2_submit_embedded_qios(tgt, &amp;list);<br>
&nbsp;}<br>
@@ -240,11 +249,15 @@ static int qcow2_merge_backward_progress(struct qcow2_target *tgt,<br>
&nbsp;<br>
&nbsp;static int qcow2_merge_backward_set_eventfd(struct qcow2_target *tgt, int efd);<br>
&nbsp;<br>
-static int qcow2_merge_backward_start(struct qcow2_target *tgt, int efd)<br>
+static int qcow2_merge_backward_start(struct qcow2_target *tgt, int efd, int depth)<br>
&nbsp;{<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct qcow2 *qcow2 = tgt-&gt;top, *lower = qcow2-&gt;lower;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct qcow2 *qcow2 = tgt-&gt;top, *lower;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int ret;<br>
&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (depth-- &gt; 0 &amp;&amp; qcow2-&gt;lower)<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qcow2 = qcow2-&gt;lower;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lower = qcow2-&gt;lower;<br>
+<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lockdep_assert_held(&amp;tgt-&gt;ctl_mutex);<br>
&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!lower)<br>
@@ -263,6 +276,7 @@ static int qcow2_merge_backward_start(struct qcow2_target *tgt, int efd)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ret)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ret;<br>
&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tgt-&gt;backward_merge.qcow2 = qcow2;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tgt-&gt;backward_merge.state = BACKWARD_MERGE_START;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __backward_merge_update_stage(tgt, BACKWARD_MERGE_STAGE_START);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tgt-&gt;backward_merge.error = 0;<br>
@@ -291,7 +305,7 @@ void qcow2_merge_backward_work(struct work_struct *work)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __backward_merge_update_stage(tgt, BACKWARD_MERGE_STAGE_BREAK_L1COW);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_unlock(&amp;tgt-&gt;ctl_mutex);<br>
&nbsp;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qcow2 = tgt-&gt;top;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qcow2 = tgt-&gt;backward_merge.qcow2;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lower = qcow2-&gt;lower;<br>
&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*<br>
@@ -300,7 +314,7 @@ void qcow2_merge_backward_work(struct work_struct *work)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * we'd have to freeze IO going to all data clusters<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * under every L1 entry related to several snapshots.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = qcow2_break_l1cow(tgt);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = qcow2_break_l1cow(tgt, qcow2);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ret) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QC_ERR(tgt-&gt;ti, &quot;Can't break L1 COW&quot;);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto out_err;<br>
@@ -316,7 +330,7 @@ void qcow2_merge_backward_work(struct work_struct *work)<br>
&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Start merge */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; backward_merge_update_stage(tgt, BACKWARD_MERGE_STAGE_RUNNING);<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = qcow2_merge_common(tgt);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = qcow2_merge_common(tgt, qcow2);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ret) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set_backward_merge_in_process(tgt, qcow2, false);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret2 = qcow2_set_image_file_features(lower, false);<br>
@@ -357,9 +371,29 @@ static int qcow2_merge_backward_complete(struct qcow2_target *tgt)<br>
&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (tgt-&gt;backward_merge.state != BACKWARD_MERGE_WAIT_COMPLETION)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -EBUSY;<br>
+<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (tgt-&gt;top == tgt-&gt;backward_merge.qcow2) {<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tgt-&gt;top = lower;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct qcow2 *top = tgt-&gt;top;<br>
+<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (top &amp;&amp; top-&gt;lower != tgt-&gt;backward_merge.qcow2)<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; top = top-&gt;lower;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!top)<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -EFAULT;<br>
+<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qcow2 = tgt-&gt;backward_merge.qcow2;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lower = qcow2-&gt;lower;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; top-&gt;lower = lower;<br>
+<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; top = tgt-&gt;top;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (top != lower) {<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; top-&gt;img_id--;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; top = top-&gt;lower;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
+<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __backward_merge_update_stage(tgt, BACKWARD_MERGE_STAGE_COMPLETING);<br>
-<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tgt-&gt;top = lower;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; smp_wmb(); /* Pairs with qcow2_ref_inc() */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qcow2_inflight_ref_switch(tgt); /* Pending qios */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qcow2_flush_deferred_activity(tgt, qcow2); /* Delayed md pages */<br>
@@ -396,7 +430,7 @@ void qcow2_merge_backward_cancel(struct qcow2_target *tgt)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (tgt-&gt;backward_merge.state == BACKWARD_MERGE_STOP) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flush = true;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (tgt-&gt;backward_merge.state == BACKWARD_MERGE_WAIT_COMPLETION) {<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set_backward_merge_in_process(tgt, tgt-&gt;top, false);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set_backward_merge_in_process(tgt, tgt-&gt;backward_merge.qcow2, false);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tgt-&gt;backward_merge.state = BACKWARD_MERGE_STOPPED;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __backward_merge_update_stage(tgt, BACKWARD_MERGE_STAGE_NONE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
@@ -572,7 +606,7 @@ int qcow2_message(struct dm_target *ti, unsigned int argc, char **argv,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct qcow2_target *tgt = to_qcow2_target(ti);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int ret = -EPERM;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u32 val, val2;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int efd;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int efd, depth = 0;<br>
&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!capable(CAP_SYS_ADMIN))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto out;<br>
@@ -652,11 +686,15 @@ int qcow2_message(struct dm_target *ti, unsigned int argc, char **argv,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (!strcmp(argv[0], &quot;merge_backward&quot;)) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* argc &gt;= 2 */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!strcmp(argv[1], &quot;start&quot;)) {<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (argc != 3 || kstrtoint(argv[2], 10, &amp;efd) || efd &lt; 0) {<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (argc &lt; 3 || argc &gt; 4 || kstrtoint(argv[2], 10, &amp;efd) || efd &lt; 0) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = -EINVAL;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto out_unlock;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = qcow2_merge_backward_start(tgt, efd);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (argc == 4 &amp;&amp; kstrtou32(argv[3], 10, &amp;depth)) {<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = -EINVAL;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto out_unlock;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = qcow2_merge_backward_start(tgt, efd, depth);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (!strcmp(argv[1], &quot;complete&quot;)) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (argc != 2) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = -EINVAL;<br>
diff --git a/drivers/md/dm-qcow2.h b/drivers/md/dm-qcow2.h<br>
index 5aa00c6a5ebd5..c2b2193561461 100644<br>
--- a/drivers/md/dm-qcow2.h<br>
+++ b/drivers/md/dm-qcow2.h<br>
@@ -172,6 +172,7 @@ enum qcow2_backward_merge_stage {<br>
&nbsp;<br>
&nbsp;struct qcow2_backward_merge {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct work_struct work;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct qcow2 *qcow2;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum qcow2_backward_merge_state state;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int error;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct eventfd_ctx *eventfd_ctx;<br>
-- <br>
2.43.5<br>
<br>
_______________________________________________<br>
Devel mailing list<br>
Devel@openvz.org<br>
<a href="https://lists.openvz.org/mailman/listinfo/devel">https://lists.openvz.org/mailman/listinfo/devel</a><br>
</div>
</span></font></div>
</body>
</html>