[PATCH] drbd: fix ldev refcount imbalance when resync request allocation fails
Björn Stabel <[email protected]> Thu, 16 Jul 2026 13:36:40 +0200
| Newsgroups | dev.linux.lists.drbd-dev |
|---|---|
| Message-ID | <[email protected]> |
make=5Fone=5Fresync=5Frequest() does not take its own ldev reference; it
relies on the reference held by its only caller, make=5Fresync=5Frequest().
Nevertheless, when drbd=5Falloc=5Fpeer=5Freq() fails, the error path called
put=5Fldev() before returning -EAGAIN. The caller then handles -EAGAIN by
jumping to request=5Fdone and eventually releases its reference again at
out=5Fput=5Fldev. The result is two put=5Fldev() calls for a single
get=5Fldev(), so device->local=5Fcnt underflows.
Once local=5Fcnt is negative, every subsequent get=5Fldev()/put=5Fldev() pa=
ir
trips D=5FASSERT(device, i >=3D 0) in put=5Fldev(), flooding the kernel log
with "ASSERTION i >=3D 0 FAILED in put=5Fldev" for every I/O completion on
the device. Worse, the "last reference dropped" detection (i =3D=3D 0) is
permanently skewed: a later detach either never sees the counter reach
zero (hanging the transition to diskless) or sees it reach zero while
references are still in flight, with use-after-free potential in the
ldev destroy path.
The allocation failure itself is expected transient behavior: resync
requests are allocated with GFP=5FTRY & ~=5F=5FGFP=5FRECLAIM on purpose, so=
the
mempool can run dry under a burst of parallel resyncs and the request is
simply retried later. Observed in production on a Proxmox/LINSTOR
cluster after ten "linstor resource toggle-disk" migrations resynced
concurrently: five volumes hit the allocation failure and spammed the
assertion at the full I/O rate afterwards.
The sister path read=5Ffor=5Fcsum() takes and releases its own reference
and is balanced. Fix make=5Fone=5Fresync=5Frequest() by dropping the stray
put=5Fldev() so the reference is released exactly once, by the caller.
Fixes: 223009b6369f ("drbd: synchronize resync with interval tree and=20
dagtags")
Signed-off-by: Christian Taeumel <[email protected]>
Co-Authored-By: Claude Fable 5 <[email protected]>
---
=C2=A0drbd/drbd=5Fsender.c | 1 -
=C2=A01 file changed, 1 deletion(-)
diff --git a/drbd/drbd=5Fsender.c b/drbd/drbd=5Fsender.c
index 907f042b4..f90d3a9f6 100644
--- a/drbd/drbd=5Fsender.c
+++ b/drbd/drbd=5Fsender.c
@@ -680,7 +680,6 @@ static int make=5Fone=5Fresync=5Frequest(struct=20
drbd=5Fpeer=5Fdevice *peer=5Fdevice, int dis
=C2=A0=E2=80=83=E2=80=83=E2=80=83=E2=80=83=E2=80=83=E2=80=83=E2=80=83=E2=
=80=83=C2=A0 =C2=A0 =C2=A0 =C2=A0size, REQ=5FOP=5FWRITE);
=C2=A0=E2=80=83=E2=80=83if (!peer=5Freq) {
=C2=A0=E2=80=83=E2=80=83=E2=80=83=E2=80=83drbd=5Ferr(device, "Could not al=
locate resync request\n");
-=E2=80=83=E2=80=83=E2=80=83=E2=80=83put=5Fldev(device);
=C2=A0=E2=80=83=E2=80=83=E2=80=83=E2=80=83return -EAGAIN;
=C2=A0=E2=80=83=E2=80=83}
--=20
2.43.0
Diese E-Mail sowie etwaige Anh=C3=A4nge enthalten vertrauliche und/oder rec=
htlich gesch=C3=BCtzte Informationen und sind ausschlie=C3=9Flich f=C3=BCr =
die im Adressfeld genannte(n) Person(en) bestimmt. Sollten Sie nicht zum vo=
rgesehenen Empf=C3=A4ngerkreis geh=C3=B6ren oder diese Nachricht irrt=C3=BC=
mlich erhalten haben, bitten wir Sie, die absendende Person zu informieren =
und die E-Mail sowie alle Anh=C3=A4nge zu l=C3=B6schen. In diesem Fall ist =
jede Kenntnisnahme, Verwendung, Weitergabe oder Vervielf=C3=A4ltigung der I=
nhalte nicht gestattet.