* [BUG] 9.3.4: resync between two Secondaries stuck at 100% - flush request never acked (2 volumes, new-peer before attach)
@ 2026-10-24 16:11 Dominic Ferard
2026-10-25 16:29 ` Philipp Reisner
0 siblings, 1 reply; 2+ messages in thread
From: Dominic Ferard @ 2026-10-24 16:11 UTC (permalink / raw)
To: drbd-dev
Hello,
On a two-volume resource, a resync between two Secondaries reaches
100% (out-of-sync 0) and never completes: the target stays
Inconsistent/SyncTarget on both volumes indefinitely. It happens when
the source was brought up with a plain "drbdadm up" and its second
volume's peer bitmap_dagtag is higher than its first volume's. We hit
it in production (two standby hosts, both Secondary while the Primary
OS is down) and have reproduced it in two VMs. Details, debugfs output
and our reading of the source are below. Please correct the analysis
if we have it wrong.
Environment
-----------
- drbd-dkms 9.3.4-1ppa1~resolute1 (GIT-hash
e59b287b199f7224468af85b68a10e83c68213f5), drbd-utils
9.35.0-1ppa1~resolute1, LINBIT PPA
- Ubuntu 26.04, kernel 7.0.0-38-generic
- 2 nodes, protocol C, 1 resource with 2 volumes, external metadata,
auto-promote no
resource r0 {
options { auto-promote no; }
net { protocol C; }
on pm1 {
node-id 0;
address 10.10.10.1:7799;
volume 0 { device /dev/drbd0; disk /dev/disk/by-partlabel/drbd-r0; meta-disk /dev/disk/by-partlabel/drbd-r0-md; }
volume 1 { device /dev/drbd1; disk /dev/disk/by-partlabel/drbd-r1; meta-disk /dev/disk/by-partlabel/drbd-r1-md; }
}
on pm2 {
node-id 1;
address 10.10.10.2:7799;
volume 0 { device /dev/drbd0; disk /dev/disk/by-partlabel/drbd-r0; meta-disk /dev/disk/by-partlabel/drbd-r0-md; }
volume 1 { device /dev/drbd1; disk /dev/disk/by-partlabel/drbd-r1; meta-disk /dev/disk/by-partlabel/drbd-r1-md; }
}
}
(Production also has al-extents 6433 and resync-controller settings;
they are not needed to reproduce.)
Reproduction
------------
Start with both nodes connected and UpToDate.
pm1: make the resource dagtag non-zero
pm1# drbdadm primary r0
pm1# dd if=/dev/urandom of=/dev/drbd0 bs=1M count=10 oflag=direct
pm1# dd if=/dev/urandom of=/dev/drbd1 bs=1M count=10 oflag=direct
pm2 goes away
pm2# drbdadm down r0
pm1 writes vol0 FIRST, then vol1, so vol1's peer bitmap_dagtag
ends up higher
pm1# dd if=/dev/urandom of=/dev/drbd0 bs=1M count=20 oflag=direct
pm1# dd if=/dev/urandom of=/dev/drbd1 bs=1M count=20 oflag=direct
pm1# drbdadm secondary r0 && drbdadm down r0
both come back as Secondary with a plain "up" (new-peer before
attach)
pm1# drbdadm up r0
pm2# drbdadm up r0
Peer slot 1 in pm1's metadata before the "up" (after apply-al):
vol0 peer[1] bitmap-dagtag 0x000000000002D000
vol1 peer[1] bitmap-dagtag 0x0000000000037000
Result: pm2 is SyncTarget on both volumes with out-of-sync 0 and stays
there (we watched for several minutes; in production it stayed for
about 15 minutes until we intervened).
debugfs, /sys/kernel/debug/drbd/resources/r0/connections/<peer>/debug:
pm1 (SyncSource), connection pm2:
resource->dagtag_sector: 225280 (0x37000, from vol1's metadata)
last_peer_ack_dagtag_seen: 0
flush_requests_dagtag: 184320 (0x2D000 = vol0's dagtag = dagtag_before_attach)
flush_sequence: 1
flush_forward_sent_mask: (empty: never acked)
pm2 (SyncTarget), connection pm1:
pending_flush_mask: pm1,
"drbdadm disconnect r0; drbdadm connect r0" on pm2 starts a 0 KB
resync that also never finishes. pm1 afterwards still shows
last_peer_ack_dagtag_seen: 0 and flush_requests_dagtag: 184320, now
with flush_sequence: 2.
"drbdadm primary r0" on pm1 plus a single 4 KiB write moves
last_peer_ack_dagtag_seen to 225288, and the resync finishes at once.
Controls (same VMs):
- Vol0 written last (so vol0's peer bitmap_dagtag is higher), plain
"up": the resync finishes. flush_requests_dagtag = 0, while
last_peer_ack_dagtag_seen is also 0.
- Equal or zero bitmap dagtags (the peer left before any writes):
finishes.
- Original order, but pm1 brought up with "drbdadm adjust --skip-net
r0" and then "drbdadm adjust r0" (attach before new-peer): finishes
in 1 s. last_peer_ack_dagtag_seen = 307208 >= flush_requests_dagtag
= 266248.
Analysis (from reading the 9.3.4 source)
----------------------------------------
1. "drbdadm up" issues new-resource, new-minor, new-peer, new-path,
peer-device-options, attach, connect (per "drbdadm -d up"), so
new-peer runs before any attach.
2. new-peer (drbd_nl.c ~5118) initialises
connection->last_peer_ack_dagtag_seen = resource->dagtag_sector,
"so that flushes can be acked even if no further writes occur". At
that point the dagtag is still 0.
3. Each attach calls update_resource_dagtag() (drbd_nl.c ~2843). The
first volume raises dagtag_sector from 0 to its max peer
bitmap_dagtag (dagtag_before_attach = 0). If the second volume's
bitmap_dagtag is higher, it sets dagtag_before_attach to the first
volume's (non-zero) value and dagtag_from_backing_dev to its own.
4. When the SyncTarget sends P_FLUSH_REQUESTS, receive_flush_requests()
(drbd_receiver.c ~5176) sees dagtag_sector ==
dagtag_from_backing_dev, so it uses dagtag_before_attach (the
non-zero vol0 value) as flush_requests_dagtag.
5. drbd_check_flush_dagtag_reached() (drbd_receiver.c ~12408) acks
only when last_peer_ack_dagtag_seen >= flush_requests_dagtag. With
no Primary anywhere, last_peer_ack_dagtag_seen never moves from 0,
so the ack never comes.
6. On the target, drbd_resync_check_finished() (drbd_sender.c ~1078)
waits on drbd_any_flush_pending(), which is resource-wide, so both
volumes stay SyncTarget. (In production, one volume had already
enabled peer replication and the other had not.)
With one volume, dagtag_before_attach stays 0 and the ack always
passes, which is why we only started seeing this after moving from
one volume to two.
Possible fixes (your call): when an attach raises dagtag_sector, also
bring last_peer_ack_dagtag_seen up on existing connections that have no
Primary peer; or clamp the flush target in receive_flush_requests() so
it cannot exceed what this node could ever see acked when it has no
Primary peers.
Workaround
----------
On the standby nodes we attach before creating the peer: an
ExecStartPre= for drbd@r0.service runs "drbdadm adjust --skip-net r0"
ahead of its normal "adjust".
Happy to test patches or gather more data; the VM reproduction takes
about two minutes.
Thanks,
Dominic Ferard
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [BUG] 9.3.4: resync between two Secondaries stuck at 100% - flush request never acked (2 volumes, new-peer before attach)
2026-10-24 16:11 [BUG] 9.3.4: resync between two Secondaries stuck at 100% - flush request never acked (2 volumes, new-peer before attach) Dominic Ferard
@ 2026-10-25 16:29 ` Philipp Reisner
0 siblings, 0 replies; 2+ messages in thread
From: Philipp Reisner @ 2026-10-25 16:29 UTC (permalink / raw)
To: Dominic Ferard; +Cc: drbd-dev
Hi Dominic,
thank you for the excellent report. Your analysis is correct. We
found the same bug independently, and the fix is already in git:
drbd-9.2: 24374f123a95 ("drbd: keep the dagtag of the last request
across several attaches")
https://github.com/LINBIT/drbd/commit/24374f123a95877956c3c95a5080b6afae75b28c
master: eec2d913473b (merge of the above into drbd-9.3)
https://github.com/LINBIT/drbd/commit/eec2d913473bf00370b1049e549f10ac0e6181cd
Only 9.3.4 is affected in practice. It is the first release that
also sends the flush to Secondaries. Earlier releases flush only
Primary peers, and a Primary's own writes move the peer acks forward.
The fix will be in 9.3.5, which we plan to release on November 9th.
If you want to confirm the fix in your VMs before then, the commit
above applies on top of 9.3.4.
Best regards,
Philipp
Am Sat, Oct 24, 2026 at 05:11:08PM +0100 schrieb Dominic Ferard:
> Hello,
>
> On a two-volume resource, a resync between two Secondaries reaches
> 100% (out-of-sync 0) and never completes: the target stays
> Inconsistent/SyncTarget on both volumes indefinitely. It happens when
> the source was brought up with a plain "drbdadm up" and its second
> volume's peer bitmap_dagtag is higher than its first volume's. We hit
> it in production (two standby hosts, both Secondary while the Primary
> OS is down) and have reproduced it in two VMs. Details, debugfs output
> and our reading of the source are below. Please correct the analysis
> if we have it wrong.
[...]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-25 16:29 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-24 16:11 [BUG] 9.3.4: resync between two Secondaries stuck at 100% - flush request never acked (2 volumes, new-peer before attach) Dominic Ferard
2026-10-25 16:29 ` Philipp Reisner
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.