From: "zhengbing.huang" <zhengbing.huang@easystack.cn>
To: drbd-dev@lists.linbit.com
Subject: [PATCH v3] drbd: Send P_PEERS_IN_SYNC only within the resync range in resync progress
Date: Tue, 23 Dec 2025 19:08:16 +0800 [thread overview]
Message-ID: <20251223110818.589784-1-zhengbing.huang@easystack.cn> (raw)
During the resync process, the range of resync is not continuous.
If the next sync position is very far from the current sync position,
it will cause the same problem as commit: e2d0439f9
("drbd: only send P_PEERS_IN_SYNC for up to 4 MiB when resync finished").
The solution is to skip the sector where there is no reysnc.
Fixes: bc218ad64640 ("drbd: only send P_PEERS_IN_SYNC every 4MiB")
Signed-off-by: zhengbing.huang <zhengbing.huang@easystack.cn>
---
drbd/drbd_int.h | 4 ++-
drbd/drbd_receiver.c | 61 +++++++++++++++++++++++++++++++++++++++++---
drbd/drbd_state.c | 1 +
3 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/drbd/drbd_int.h b/drbd/drbd_int.h
index 68991ab93..0bfcd0f0a 100644
--- a/drbd/drbd_int.h
+++ b/drbd/drbd_int.h
@@ -1379,6 +1379,7 @@ struct drbd_peer_device {
enum drbd_disk_state resync_finished_pdsk; /* Finished while starting resync */
int resync_again; /* decided to resync again while resync running */
sector_t last_peers_in_sync_end; /* sector after end of last scheduled peers-in-sync */
+ sector_t last_in_sync_end; /* sector of the last in sync and not update */
unsigned long resync_next_bit; /* bitmap bit to search from for next resync request */
unsigned long last_resync_pass_bits; /* bitmap weight at end of previous pass */
@@ -2014,7 +2015,8 @@ static inline sector_t device_bit_to_kb(struct drbd_device *device, unsigned lon
* extent shift since the P_PEERS_IN_SYNC intervals are broken up based on
* activity log extents anyway. */
#define PEERS_IN_SYNC_STEP_SHIFT AL_EXTENT_SHIFT
-#define PEERS_IN_SYNC_STEP_SECT_MASK ((1UL << (PEERS_IN_SYNC_STEP_SHIFT - SECTOR_SHIFT)) - 1)
+#define PEERS_IN_SYNC_STEP_SECT (1UL << (PEERS_IN_SYNC_STEP_SHIFT - SECTOR_SHIFT))
+#define PEERS_IN_SYNC_STEP_SECT_MASK (PEERS_IN_SYNC_STEP_SECT - 1)
/* Indexed external meta data has a fixed on-disk size of 128MiB, of which
* 4KiB are our "superblock", and 32KiB are the fixed size activity
diff --git a/drbd/drbd_receiver.c b/drbd/drbd_receiver.c
index 3eed5d33e..08fd20b14 100644
--- a/drbd/drbd_receiver.c
+++ b/drbd/drbd_receiver.c
@@ -2350,11 +2350,17 @@ void drbd_queue_update_peers(struct drbd_peer_device *peer_device,
}
}
-static void drbd_peers_in_sync_progress(struct drbd_peer_device *peer_device, sector_t sector_end)
+static void drbd_peers_in_sync_progress(struct drbd_peer_device *peer_device,
+ sector_t sector_start, sector_t sector_end)
{
+ sector_t tmp_peers_in_sync_end, last_in_sync_end;
+ sector_t peers_in_sync_start = sector_start & ~PEERS_IN_SYNC_STEP_SECT_MASK;
/* Round down to the boundary defined by PEERS_IN_SYNC_STEP_SHIFT. */
sector_t peers_in_sync_end = sector_end & ~PEERS_IN_SYNC_STEP_SECT_MASK;
+ last_in_sync_end = peer_device->last_in_sync_end;
+ peer_device->last_in_sync_end = sector_end;
+
/* If we move backwards then move marker back. */
if (peers_in_sync_end < peer_device->last_peers_in_sync_end) {
peer_device->last_peers_in_sync_end = peers_in_sync_end;
@@ -2365,8 +2371,54 @@ static void drbd_peers_in_sync_progress(struct drbd_peer_device *peer_device, se
if (peers_in_sync_end == peer_device->last_peers_in_sync_end)
return;
- drbd_queue_update_peers(peer_device, peer_device->last_peers_in_sync_end, peers_in_sync_end);
- peer_device->last_peers_in_sync_end = peers_in_sync_end;
+ tmp_peers_in_sync_end = min(get_capacity(peer_device->device->vdisk),
+ (peer_device->last_peers_in_sync_end | PEERS_IN_SYNC_STEP_SECT_MASK) + 1);
+ D_ASSERT(peer_device, last_in_sync_end >= peer_device->last_peers_in_sync_end &&
+ last_in_sync_end < tmp_peers_in_sync_end);
+ /* We need to consider two cases here:
+ * If last_in_sync_end has crossed last_peers_in_sync_end,
+ * we need to schedule an update. Also, if sector_start is before
+ * tmp_peers_in_sync_end, we need to schedule an update.
+ *
+ * Condition A: last_in_sync_end has advanced beyond last_peers_in_sync_end
+ *
+ * last_peers_in_sync_end tmp_peers_in_sync_end
+ * ↓ ↓
+ * --------|--------- 4MiB --------------|---------
+ * [--- last_in_sync_end ---]
+ *
+ * Condition B: New I/O starts before the next boundary
+ *
+ * last_peers_in_sync_end tmp_peers_in_sync_end
+ * ↓ ↓
+ * --------|--------- 4MiB --------------|---------
+ * ↓ ↓
+ * |-- sector_start -|-- sector_end --|
+ */
+ if (last_in_sync_end > peer_device->last_peers_in_sync_end ||
+ sector_start < tmp_peers_in_sync_end)
+ drbd_queue_update_peers(peer_device, peer_device->last_peers_in_sync_end,
+ tmp_peers_in_sync_end);
+
+ /* If has no resync range between peers_in_sync_start and
+ * tmp_peers_in_sync_end, we need to skip it.
+ *
+ * And if new resync range has over 4MiB, we need to update again.
+ *
+ * tmp_peers_in_sync_end peers_in_sync_start peers_in_sync_end
+ * ↓ ↓ ↓
+ * --------|---- ... 4MiB * n ... ------|--------- 4MiB --------------|---------
+ * ↓ ↓
+ * |-- sector_start -|-- sector_end --|
+ */
+ if (peers_in_sync_start > tmp_peers_in_sync_end)
+ tmp_peers_in_sync_end = peers_in_sync_start;
+ if (peers_in_sync_end - tmp_peers_in_sync_end >= PEERS_IN_SYNC_STEP_SECT) {
+ drbd_queue_update_peers(peer_device, tmp_peers_in_sync_end, peers_in_sync_end);
+ tmp_peers_in_sync_end = peers_in_sync_end;
+ }
+
+ peer_device->last_peers_in_sync_end = tmp_peers_in_sync_end;
/* Also consider scheduling a bitmap update to reduce the size of the
* next resync if this one is disrupted. */
@@ -2391,7 +2443,8 @@ static void drbd_check_peers_in_sync_progress(struct drbd_peer_device *peer_devi
spin_unlock_irq(&connection->peer_reqs_lock);
list_for_each_entry_safe(peer_req, tmp, &completed, recv_order) {
- drbd_peers_in_sync_progress(peer_device, peer_req->i.sector + (peer_req->i.size >> SECTOR_SHIFT));
+ drbd_peers_in_sync_progress(peer_device, peer_req->i.sector,
+ peer_req->i.sector + (peer_req->i.size >> SECTOR_SHIFT));
drbd_free_peer_req(peer_req);
}
}
diff --git a/drbd/drbd_state.c b/drbd/drbd_state.c
index 28c89c2be..9b0dd97d4 100644
--- a/drbd/drbd_state.c
+++ b/drbd/drbd_state.c
@@ -2722,6 +2722,7 @@ static void initialize_resync(struct drbd_peer_device *peer_device)
unsigned long now = jiffies;
peer_device->last_peers_in_sync_end = 0;
+ peer_device->last_in_sync_end = 0;
peer_device->resync_next_bit = 0;
peer_device->last_resync_pass_bits = tw;
peer_device->rs_failed = 0;
--
2.43.0
next reply other threads:[~2025-12-23 11:23 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-23 11:08 zhengbing.huang [this message]
2025-12-23 15:31 ` [PATCH v3] drbd: Send P_PEERS_IN_SYNC only within the resync range in resync progress Joel Colledge
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251223110818.589784-1-zhengbing.huang@easystack.cn \
--to=zhengbing.huang@easystack.cn \
--cc=drbd-dev@lists.linbit.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox