<div style="line-height:1.7;color:#000000;font-size:14px;font-family:Arial"><br><pre>Hi Philipp,</pre>Under the new <span style="white-space: pre-wrap">condition<span style="white-space: normal">, if the value of susp_uuid is {true, true}, the </span><span style="white-space: pre-wrap">condition <span style="white-space: normal">returns true.</span></span></span><pre>-               if (create_new_uuid)
+               /* When susp_uuid goes from true to false, we just created a new
+                * current-uuid, it is pointless to do this one more time
+                */
+               if (create_new_uuid &amp;&amp; !(susp_uuid[OLD] &amp;&amp; !susp_uuid[NEW]))
                       set_bit(__NEW_CUR_UUID, &amp;device-&gt;flags);</pre><div>if <span style="white-space: pre-wrap">create_new_uuid is true, and </span><span style="white-space: pre-wrap">susp_uuid is {true, true}, the condition is satisfied.</span></div><div><span style="white-space: pre-wrap">__NEW_CUR_UUID will be set.</span></div><div  style="position:relative;zoom:1"></div><div><span style="white-space: pre-wrap"><br></span></div><div><pre>best regards,<br>Zhengbing<br></pre></div><div><span style="white-space: pre-wrap"><br></span></div><pre><br>From: Philipp Reisner &lt;philipp.reisner@linbit.com&gt;
Date: 2023-12-07 13:35:28
To:  "黄正兵" &lt;zhengbing.huang@easystack.cn&gt;
Cc:  dongsheng.yang@easystack.cn,drbd-dev@lists.linbit.com,Lars Ellenberg &lt;lars.ellenberg@linbit.com&gt;
Subject: Re: Re: Re: [PATCH] drbd: when change susp_uuid[NEW] to true, make sure susp_uuid[OLD] is false&gt;Hello Zhengbing,
&gt;
&gt;no, I disagree. The code is good as it is since commit e31d63966fac73fc000b.
&gt;
&gt;Here is my explanation:
&gt;
&gt;IO is frozen because the resource lost quorum. The user changes the config
&gt;and reduces the quorum setting to 1.
&gt;
&gt;The regular sequence is:
&gt;
&gt;1. in sanitize_state()
&gt;   susp_uuid = { false, true }
&gt;   DRBD keeps the resource suspended longer.
&gt;
&gt;2. in finish_state_change()
&gt;   it sets __NEW_CUR_UUIC and that moves to NEW_CUR_UUID later.
&gt;
&gt;   in w_after_state_change()
&gt;3a when susp_uuid goes from false -&gt; true then drbd_uuid_new_current()
&gt;3b Trigger another state change that sets susp_uuuid[NEW] back to false.
&gt;
&gt;1. sanitize_sate()    susp_uuid = { true, false }
&gt;2. in finish_state_change() nothing relevant happens
&gt;3a no positive edge on susp_uuid no NEW_CUR_UUID bit nothing happens
&gt;3b susp_uuid[NEW] == false -&gt; nothing happens
&gt;
&gt;
&gt;Now let us assume between 3a and 3b, another CPU does an unrelated
&gt;state change that usually triggers a new current uuid:
&gt;
&gt;CPU0:
&gt;1. in sanitize_state()
&gt;   susp_uuid = { false, true }
&gt;   DRBD keeps the resource suspended longer.
&gt;
&gt;2. in finish_state_change()
&gt;   it sets __NEW_CUR_UUIC and that moves to NEW_CUR_UUID later.
&gt;
&gt;   in w_after_state_change()
&gt;3a when susp_uuid goes from false -&gt; true
&gt;   drbd_uuid_new_current()
&gt;
&gt;    CPU1:
&gt;    Here, another thread starts another unrelated state change
&gt;    that again wants to set NEW_CUR_UUID. But let us go into the details.
&gt;
&gt;    1. in sanitize_state() susp_uuid = { true, true }
&gt;    2. in finish_state_chanage() it does _NOT_ set __NEW_CUR_UUID
&gt;       because the condition only allows it, when we have a
&gt;       positive edge on susp_uuid (= susp_uuid = { false, true })
&gt;       But this time, it is susp_uuid = { true, true }. No edge.
&gt;       so __NEW_CUR_UUID stays 0 -&gt; NEW_CUR_UUID stays 0
&gt;    3a nothing, since no NEW_CUR_UUID
&gt;    3b creates a state change to set susp_uuid[NEW] to false
&gt;
&gt;CPU: continues with w_after_state()
&gt;3b Trigger another state change that sets susp_uuuid[NEW] back to false.
&gt;   This is an "empty state change" as it is false and does nothing.
&gt;
&gt;
&gt;I think you have a mistake in your reasoning at T3.
&gt;
&gt;best regards,
&gt; Philipp
&gt;
&gt;On Mon, Nov 27, 2023 at 3:48 PM 黄正兵 &lt;zhengbing.huang@easystack.cn&gt; wrote:
&gt;&gt;
&gt;&gt; Hi Philipp,
&gt;&gt;
&gt;&gt;
&gt;&gt; The third point about modification is that it may not cover all scenarios.
&gt;&gt;
&gt;&gt; In w_after_state_change(), between generating the new current_uuid and
&gt;&gt; clearing the susp_uuid, it is possible that another thread set the __NEW_CUR_UUID flag.
&gt;&gt;
&gt;&gt; The problem scenario is as follows:
&gt;&gt;
&gt;&gt; T1:
&gt;&gt; begin_state_change()
&gt;&gt; end_state_change()
&gt;&gt;   __end_state_change()
&gt;&gt;     ___end_state_change()
&gt;&gt;     # susp_uuid value is {True, True}
&gt;&gt;       T2: w_after_state_change()
&gt;&gt;             drbd_uuid_new_current()
&gt;&gt;
&gt;&gt;                                                                               T3:
&gt;&gt;                                                                                     begin_state_change()
&gt;&gt;                                                                                     # set __NEW_CUR_UUID flag
&gt;&gt;                                                                                     end_state_change()
&gt;&gt;
&gt;&gt;             begin_state_change()
&gt;&gt;             # set susp_uuid[NEW] = False
&gt;&gt;             end_state_change()
&gt;&gt;
&gt;&gt; In the end, the NEW_CUR_UUID flag bit is generated and not cleaned up.
&gt;&gt;
&gt;&gt; Therefore, the third point about modification can be change to this:
&gt;&gt;
&gt;&gt; diff --git a/drbd/drbd_state.c b/drbd/drbd_state.c
&gt;&gt; index e35150340..2101c0ebc 100644
&gt;&gt; --- a/drbd/drbd_state.c
&gt;&gt; +++ b/drbd/drbd_state.c
&gt;&gt; @@ -2553,6 +2553,7 @@ static bool should_try_become_up_to_date(struct drbd_device *device, enum drbd_d
&gt;&gt;  static void finish_state_change(struct drbd_resource *resource, const char *tag)
&gt;&gt;  {
&gt;&gt;         enum drbd_role *role = resource-&gt;role;
&gt;&gt; +       bool *susp_uuid = resource-&gt;susp_uuid;
&gt;&gt;         struct drbd_device *device;
&gt;&gt;         struct drbd_connection *connection;
&gt;&gt;         bool starting_resync = false;
&gt;&gt; @@ -2828,7 +2829,7 @@ static void finish_state_change(struct drbd_resource *resource, const char *tag)
&gt;&gt;                 if (role[OLD] == R_SECONDARY &amp;&amp; role[NEW] == R_PRIMARY)
&gt;&gt;                         create_new_uuid = true;
&gt;&gt;
&gt;&gt; -               if (create_new_uuid)
&gt;&gt; +               if (create_new_uuid &amp;&amp; !susp_uuid[OLD])
&gt;&gt;                         set_bit(__NEW_CUR_UUID, &amp;device-&gt;flags);
&gt;&gt;
&gt;&gt;                 if (disk_state[NEW] != D_NEGOTIATING &amp;&amp; get_ldev_if_state(device, D_DETACHING)) {
&gt;&gt;
&gt;&gt; best regards,
&gt;&gt; Zhengbing
&gt;&gt;
&gt;&gt;
&gt;&gt;
&gt;&gt;
&gt;&gt;
&gt;&gt; From: Philipp Reisner &lt;philipp.reisner@linbit.com&gt;
&gt;&gt; Date: 2023-11-25 15:47:16
&gt;&gt; To:  "黄正兵" &lt;zhengbing.huang@easystack.cn&gt;
&gt;&gt; Cc:  dongsheng.yang@easystack.cn,drbd-dev@lists.linbit.com
&gt;&gt; Subject: Re: Re: [PATCH] drbd: when change susp_uuid[NEW] to true, make sure susp_uuid[OLD] is false&gt;Hi Zhengbing,
&gt;&gt; &gt;
&gt;&gt; &gt;Lars and I came up with this:
&gt;&gt; &gt;
&gt;&gt; &gt;commit e31d63966fac73fc000b584ccb2580016eccda17
&gt;&gt; &gt;Author: Philipp Reisner &lt;philipp.reisner@linbit.com&gt;
&gt;&gt; &gt;Date:   Thu Nov 23 06:31:28 2023 +0100
&gt;&gt; &gt;
&gt;&gt; &gt;   drbd: fix susp_uuid clearing
&gt;&gt; &gt;
&gt;&gt; &gt;   I introduced susp_uuid for keeping a resource longer suspended for
&gt;&gt; &gt;   writing a new current-uuid.
&gt;&gt; &gt;   But in the following scenario, it failed to clear the susp_uuid bit:
&gt;&gt; &gt;
&gt;&gt; &gt;    1. The network connection between a primary and secondary node
&gt;&gt; &gt;       fails. The primary has the setting quorum=2. IO freezes on the
&gt;&gt; &gt;       primary node.
&gt;&gt; &gt;
&gt;&gt; &gt;    2. The user changes the quorum setting from 2 to one. The primary
&gt;&gt; &gt;       node generates a new current-uuid and clears the susp_uuid bit in
&gt;&gt; &gt;       a second state change.
&gt;&gt; &gt;
&gt;&gt; &gt;    3. If, during the second state change, another condition for creating
&gt;&gt; &gt;       a new current UUID evaluates to true, the code fails to clear the
&gt;&gt; &gt;       suspen_uuid bit.
&gt;&gt; &gt;
&gt;&gt; &gt;   Fixing this in three places:
&gt;&gt; &gt;    1. in sanitize_state(): Only set susp_uuid[NEW] if susp_uuid[OLD]
&gt;&gt; &gt;       was not set. That avoids it happening a second time after
&gt;&gt; &gt;       one iteration.
&gt;&gt; &gt;
&gt;&gt; &gt;    2. in w_after_state_chage(): Always end the cycle by setting clearing
&gt;&gt; &gt;       susp_uuid[NEW] if it is set. (Independently of susp_uuid[OLD].
&gt;&gt; &gt;
&gt;&gt; &gt;    3. in finish_sate_change(): Do not set NEW_CUR_UUID again if we are
&gt;&gt; &gt;       in this operation.
&gt;&gt; &gt;
&gt;&gt; &gt;   Strictly speaking, (2) is unnecessary after (1), but I also do it
&gt;&gt; &gt;   since it shortens the code. Also, (3) alone would fix the issue.
&gt;&gt; &gt;
&gt;&gt; &gt;   Fixes: d47f7456ab ("drbd: create new UUID before resuming IO upon
&gt;&gt; &gt;   regaining quorum")
&gt;&gt; &gt;
&gt;&gt; &gt;   Co-developed-by: zhengbing.huang &lt;zhengbing.huang@easystack.cn&gt;
&gt;&gt; &gt;   Co-developed-by: Lars Ellenberg &lt;lars.ellenberg@linbit.com&gt;
&gt;&gt; &gt;
&gt;&gt; &gt;diff --git a/drbd/drbd_state.c b/drbd/drbd_state.c
&gt;&gt; &gt;index e35150340..b884bb622 100644
&gt;&gt; &gt;--- a/drbd/drbd_state.c
&gt;&gt; &gt;+++ b/drbd/drbd_state.c
&gt;&gt; &gt;@@ -2353,7 +2353,8 @@ static void sanitize_state(struct drbd_resource *resource)
&gt;&gt; &gt;       resource-&gt;susp_quorum[NEW] =
&gt;&gt; &gt;               resource-&gt;res_opts.on_no_quorum == ONQ_SUSPEND_IO ?
&gt;&gt; &gt;!resource_has_quorum : false;
&gt;&gt; &gt;
&gt;&gt; &gt;-       if (resource_is_suspended(resource, OLD) &amp;&amp;
&gt;&gt; &gt;!resource_is_suspended(resource, NEW)) {
&gt;&gt; &gt;+       if (!resource-&gt;susp_uuid[OLD] &amp;&amp;
&gt;&gt; &gt;+           resource_is_suspended(resource, OLD) &amp;&amp;
&gt;&gt; &gt;!resource_is_suspended(resource, NEW)) {
&gt;&gt; &gt;               idr_for_each_entry(&amp;resource-&gt;devices, device, vnr) {
&gt;&gt; &gt;                       if (test_bit(NEW_CUR_UUID, &amp;device-&gt;flags)) {
&gt;&gt; &gt;                               resource-&gt;susp_uuid[NEW] = true;
&gt;&gt; &gt;@@ -2553,6 +2554,7 @@ static bool should_try_become_up_to_date(struct
&gt;&gt; &gt;drbd_device *device, enum drbd_d
&gt;&gt; &gt;static void finish_state_change(struct drbd_resource *resource, const char *tag)
&gt;&gt; &gt;{
&gt;&gt; &gt;       enum drbd_role *role = resource-&gt;role;
&gt;&gt; &gt;+       bool *susp_uuid = resource-&gt;susp_uuid;
&gt;&gt; &gt;       struct drbd_device *device;
&gt;&gt; &gt;       struct drbd_connection *connection;
&gt;&gt; &gt;       bool starting_resync = false;
&gt;&gt; &gt;@@ -2828,7 +2830,10 @@ static void finish_state_change(struct
&gt;&gt; &gt;drbd_resource *resource, const char *tag)
&gt;&gt; &gt;               if (role[OLD] == R_SECONDARY &amp;&amp; role[NEW] == R_PRIMARY)
&gt;&gt; &gt;                       create_new_uuid = true;
&gt;&gt; &gt;
&gt;&gt; &gt;-               if (create_new_uuid)
&gt;&gt; &gt;+               /* When susp_uuid goes from true to false, we just created a new
&gt;&gt; &gt;+                * current-uuid, it is pointless to do this one more time
&gt;&gt; &gt;+                */
&gt;&gt; &gt;+               if (create_new_uuid &amp;&amp; !(susp_uuid[OLD] &amp;&amp; !susp_uuid[NEW]))
&gt;&gt; &gt;                       set_bit(__NEW_CUR_UUID, &amp;device-&gt;flags);
&gt;&gt; &gt;
&gt;&gt; &gt;               if (disk_state[NEW] != D_NEGOTIATING &amp;&amp;
&gt;&gt; &gt;get_ldev_if_state(device, D_DETACHING)) {
&gt;&gt; &gt;@@ -4189,7 +4194,7 @@ static int w_after_state_change(struct drbd_work
&gt;&gt; &gt;*w, int unused)
&gt;&gt; &gt;                       still_connected = true;
&gt;&gt; &gt;       }
&gt;&gt; &gt;
&gt;&gt; &gt;-       if (!susp_uuid[OLD] &amp;&amp; susp_uuid[NEW]) {
&gt;&gt; &gt;+       if (susp_uuid[NEW]) {
&gt;&gt; &gt;               unsigned long irq_flags;
&gt;&gt; &gt;
&gt;&gt; &gt;               begin_state_change(resource, &amp;irq_flags, CS_VERBOSE);
&gt;&gt; &gt;
&gt;&gt; &gt;On Thu, Nov 23, 2023 at 9:48 AM 黄正兵 &lt;zhengbing.huang@easystack.cn&gt; wrote:
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; Hi Philipp,
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; Such modifications may cause new problems.
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt;  If, during the second state change,  the NEW_CUR_UUID flag was not cleared.
&gt;&gt; &gt;&gt;  clears the susp_uuid bit in a  thirdly state change.
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; Eventually, it becomes an endless cycle.
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; So, is it possible to add the following modifications:
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; diff --git a/drbd/drbd_state.c b/drbd/drbd_state.c
&gt;&gt; &gt;&gt; index 2fbd0b1..6bd6431 100644
&gt;&gt; &gt;&gt; --- a/drbd/drbd_state.c
&gt;&gt; &gt;&gt; +++ b/drbd/drbd_state.c
&gt;&gt; &gt;&gt; @@ -3938,9 +3938,13 @@ static int w_after_state_change(struct drbd_work *w, int unused)
&gt;&gt; &gt;&gt;                                 drbd_maybe_khelper(device, connection, "disconnected");
&gt;&gt; &gt;&gt;                 }
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; -               if (!susp_uuid[OLD] &amp;&amp; susp_uuid[NEW] &amp;&amp;
&gt;&gt; &gt;&gt; -                   test_and_clear_bit(NEW_CUR_UUID, &amp;device-&gt;flags))
&gt;&gt; &gt;&gt; -                       new_current_uuid = true;
&gt;&gt; &gt;&gt; +               if (susp_uuid[NEW]) {
&gt;&gt; &gt;&gt; +                       if (susp_uuid[OLD])
&gt;&gt; &gt;&gt; +                               clear_bit(NEW_CUR_UUID, &amp;device-&gt;flags);
&gt;&gt; &gt;&gt; +                       else if (test_and_clear_bit(NEW_CUR_UUID, &amp;device-&gt;flags))) {
&gt;&gt; &gt;&gt; +                               new_curr_uuid = true;
&gt;&gt; &gt;&gt; +                       }
&gt;&gt; &gt;&gt; +               }
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt;                 if (new_current_uuid)
&gt;&gt; &gt;&gt;                         drbd_uuid_new_current(device, false);
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; best regards,
&gt;&gt; &gt;&gt; Zhengbing
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; From: Philipp Reisner &lt;philipp.reisner@linbit.com&gt;
&gt;&gt; &gt;&gt; Date: 2023-11-23 14:06:30
&gt;&gt; &gt;&gt; To:  "zhengbing.huang" &lt;zhengbing.huang@easystack.cn&gt;
&gt;&gt; &gt;&gt; Cc:  drbd-dev@lists.linbit.com,joel.colledge@linbit.com
&gt;&gt; &gt;&gt; Subject: Re: [PATCH] drbd: when change susp_uuid[NEW] to true, make sure susp_uuid[OLD] is false&gt;Hello Zhengbing,
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;Thank you for pointing this out. I created a little bit different patch.
&gt;&gt; &gt;&gt; &gt;First, the sanitize_state() function should clean up the new state,
&gt;&gt; &gt;&gt; &gt;but I think it should never change the old state.
&gt;&gt; &gt;&gt; &gt;It can not rewrite history.
&gt;&gt; &gt;&gt; &gt;Second, we do not want to create two new current-uuids while I/O is frozen.
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;    drbd: fix susp_uuid clearing
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;   I introduced susp_uuid for keeping a resource longer suspended for
&gt;&gt; &gt;&gt; &gt;   writing a new current-uuid.
&gt;&gt; &gt;&gt; &gt;   But in the following scenario, it failed to clear the susp_uuid bit:
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;    1. The network connection between a primary and secondary node
&gt;&gt; &gt;&gt; &gt;    fails. The primary has the setting quorum=2. IO freezes on the
&gt;&gt; &gt;&gt; &gt;    primary node.
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;    2. The user changes the quorum setting from 2 to one. The primary
&gt;&gt; &gt;&gt; &gt;    node generates a new current-uuid and clears the susp_uuid bit in a
&gt;&gt; &gt;&gt; &gt;    second state change.
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;    3. If, during the second state change, another condition for creating
&gt;&gt; &gt;&gt; &gt;    a new current UUID evaluates to true, the code fails to clear the
&gt;&gt; &gt;&gt; &gt;    suspen_uuid bit.
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;   The second attempt to create a new current-uuid gets ignored since it
&gt;&gt; &gt;&gt; &gt;   is pointless to create two current-uuids while I/O is frozen.
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;   Fixes: d47f7456ab ("drbd: create new UUID before resuming IO upon
&gt;&gt; &gt;&gt; &gt;   regaining quorum")
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;   Co-developed-by: zhengbing.huang &lt;zhengbing.huang@easystack.cn&gt;
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;diff --git a/drbd/drbd_state.c b/drbd/drbd_state.c
&gt;&gt; &gt;&gt; &gt;index e35150340..316d3fd39 100644
&gt;&gt; &gt;&gt; &gt;--- a/drbd/drbd_state.c
&gt;&gt; &gt;&gt; &gt;+++ b/drbd/drbd_state.c
&gt;&gt; &gt;&gt; &gt;@@ -4189,7 +4189,7 @@ static int w_after_state_change(struct drbd_work
&gt;&gt; &gt;&gt; &gt;*w, int unused)
&gt;&gt; &gt;&gt; &gt;                       still_connected = true;
&gt;&gt; &gt;&gt; &gt;       }
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;-       if (!susp_uuid[OLD] &amp;&amp; susp_uuid[NEW]) {
&gt;&gt; &gt;&gt; &gt;+       if (susp_uuid[NEW]) {
&gt;&gt; &gt;&gt; &gt;               unsigned long irq_flags;
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;               begin_state_change(resource, &amp;irq_flags, CS_VERBOSE);
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;I give this to internal review for merging.
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;best regards,
&gt;&gt; &gt;&gt; &gt; Philipp
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;
&gt;&gt; &gt;&gt; &gt;On Wed, Nov 22, 2023 at 4:25 AM zhengbing.huang
&gt;&gt; &gt;&gt; &gt;&lt;zhengbing.huang@easystack.cn&gt; wrote:
&gt;&gt; &gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; &gt;&gt; The problem scenario is as follows:
&gt;&gt; &gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; &gt;&gt; 1. drbd is built on two nodes, role is primary and secondary, quorum is 2.
&gt;&gt; &gt;&gt; &gt;&gt;    then drbd's network fails. IO will be suspended.
&gt;&gt; &gt;&gt; &gt;&gt; 2. primary modify quorum to 1, during this state change,
&gt;&gt; &gt;&gt; &gt;&gt;    drbd will set susp_uuid[NEW] to true and generate a new UUID.
&gt;&gt; &gt;&gt; &gt;&gt; 3. then in w_after_state_change, start the second state change,
&gt;&gt; &gt;&gt; &gt;&gt;    set susp_uuid[NEW] to false. but during the second state change,
&gt;&gt; &gt;&gt; &gt;&gt;    it's possible to find NEW_CUR_UUID flag was set by others.
&gt;&gt; &gt;&gt; &gt;&gt;    then sanitize_state() will set susp_uuid[NEW] to true.
&gt;&gt; &gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; &gt;&gt; Finally susp_uuid value is {true, true}, IO is frozen.
&gt;&gt; &gt;&gt; &gt;&gt; And there is no way to set susp_uuid to false after that.
&gt;&gt; &gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; &gt;&gt; So, while susp_uuid[NEW] is set to true, we want susp_uuid[OLD] to be false.
&gt;&gt; &gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; &gt;&gt; Fixes: d47f7456ab ("drbd: create new UUID before resuming IO upon regaining quorum")
&gt;&gt; &gt;&gt; &gt;&gt; Signed-off-by: zhengbing.huang &lt;zhengbing.huang@easystack.cn&gt;
&gt;&gt; &gt;&gt; &gt;&gt; ---
&gt;&gt; &gt;&gt; &gt;&gt;  drbd/drbd_state.c | 1 +
&gt;&gt; &gt;&gt; &gt;&gt;  1 file changed, 1 insertion(+)
&gt;&gt; &gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt; &gt;&gt; diff --git a/drbd/drbd_state.c b/drbd/drbd_state.c
&gt;&gt; &gt;&gt; &gt;&gt; index e35150340..0dedd2dae 100644
&gt;&gt; &gt;&gt; &gt;&gt; --- a/drbd/drbd_state.c
&gt;&gt; &gt;&gt; &gt;&gt; +++ b/drbd/drbd_state.c
&gt;&gt; &gt;&gt; &gt;&gt; @@ -2356,6 +2356,7 @@ static void sanitize_state(struct drbd_resource *resource)
&gt;&gt; &gt;&gt; &gt;&gt;         if (resource_is_suspended(resource, OLD) &amp;&amp; !resource_is_suspended(resource, NEW)) {
&gt;&gt; &gt;&gt; &gt;&gt;                 idr_for_each_entry(&amp;resource-&gt;devices, device, vnr) {
&gt;&gt; &gt;&gt; &gt;&gt;                         if (test_bit(NEW_CUR_UUID, &amp;device-&gt;flags)) {
&gt;&gt; &gt;&gt; &gt;&gt; +                               resource-&gt;susp_uuid[OLD] = false;
&gt;&gt; &gt;&gt; &gt;&gt;                                 resource-&gt;susp_uuid[NEW] = true;
&gt;&gt; &gt;&gt; &gt;&gt;                                 break;
&gt;&gt; &gt;&gt; &gt;&gt;                         }
&gt;&gt; &gt;&gt; &gt;&gt; --
&gt;&gt; &gt;&gt; &gt;&gt; 2.17.1
&gt;&gt; &gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt;
&gt;&gt; &gt;&gt;
&gt;&gt;
&gt;&gt;
</pre></div><br>