Skip to content

drbd 9.2.19-flant.11: fix multi-source resync deadlock (cancel-on-pause)#13

Open
astef wants to merge 1 commit into
flant-9.2from
astef-drbd-9.2.19-flant.11
Open

drbd 9.2.19-flant.11: fix multi-source resync deadlock (cancel-on-pause)#13
astef wants to merge 1 commit into
flant-9.2from
astef-drbd-9.2.19-flant.11

Conversation

@astef

@astef astef commented Jul 23, 2026

Copy link
Copy Markdown
Member

Summary

Fixes the stuck-resync-after-reboot bug: ~5% of a rebooted node's replicas froze mid-resync at done:X% and never completed.

Root cause (multi-source resync conflict deadlock): when a device is resynced from two peers at once, drbd_select_sync_target() keeps only one active L_SYNC_TARGET and forces the other to L_PAUSED_SYNC_T. The paused source goes resync-suspended:peer and never delivers replies, so a resync request already sent to it stays READY_TO_SEND forever. Via the conflict rule in drbd_should_defer_to_interval() it permanently blocks the active source's resync write for the same block, and drbd_release_conflicts() only re-drives a parked write when a conflicting interval completes — which never happens. The resync deadlocks at done:X%.

This is stock LINBIT interval-tree resync machinery (present in 9.2.x and 9.3), not a flant regression.

Fix

New drbd_cancel_paused_resync_requests() (drbd/drbd_req.c), called from w_after_state_change() (drbd/drbd_state.c) when a peer enters L_PAUSED_SYNC_T. Under interval_lock it drops that peer's dangling (sent, not-yet-received) resync requests and calls drbd_release_conflicts() first so the active source's parked write is re-driven. Affected blocks stay out-of-sync in the bitmap and are resynced by the active source, or by the peer once it resumes.

  • drbd/drbd_req.cdrbd_cancel_paused_resync_requests() (+68)
  • drbd/drbd_state.c — call on L_PAUSED_SYNC_T entry (+8)
  • drbd/drbd_int.h — declaration (+1)
  • version bump to 9.2.19-flant.11 (config/spec/changelogs/dockerfiles)

Test plan

  • Deployed to a 4-node R3-diskful cluster; hard reboot -f of a node with 76 UpToDate replicas → all 76 resynced with 0 done:X% freezes (baseline flant.10 was ~4–5%).
  • Two live multi-source resyncs caught in the exact SyncTarget + PausedSyncT(resync-suspended:dependency) shape progressed to UpToDate instead of freezing.
  • Three long-stuck (>1 day) casualties auto-healed once the fix loaded.

When a device is resynced from two peers at once, drbd_select_sync_target()
keeps one active L_SYNC_TARGET and forces the other to L_PAUSED_SYNC_T. The
paused source goes resync-suspended:peer and never delivers replies, so a
resync request already sent to it stays "ready-to-send" forever, and via the
conflict rule in drbd_should_defer_to_interval() it permanently blocks the
ACTIVE source's resync write for the same block. drbd_release_conflicts()
only re-drives a parked write when a conflicting interval completes, which
never happens -> resync freezes at done:X% (~5% of replicas after a reboot).

Fix: drbd_cancel_paused_resync_requests(), called from w_after_state_change()
when a peer enters L_PAUSED_SYNC_T, drops that peer's dangling (sent, not yet
received) resync requests and releases the writes parked behind them. The
blocks stay out-of-sync in the bitmap and are resynced by the active source,
or by this peer once it resumes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant