[linstor] Update piraeus-server patches with critical fixes (#1850)
## What this PR does This PR updates piraeus-server patches to address several critical production issues with DRBD resources and LUKS encryption: 1. **Add fix-duplicate-tcp-ports.diff** - Prevents duplicate TCP ports after toggle-disk operations (upstream PR #476) 2. **Update skip-adjust-when-device-inaccessible.diff** - Comprehensive fix for multiple issues: - Resources stuck in StandAlone state after node reboot - Unknown state race condition during satellite restart - Encrypted LUKS resource deletion failures - Network reconnect blocked by unavailable child device checks These patches resolve scenarios where DRBD resources fail to automatically reconnect after node reboots and improve LUKS resource lifecycle management. Upstream PRs: - https://github.com/LINBIT/linstor-server/pull/476 - https://github.com/LINBIT/linstor-server/pull/477 ### Release note ```release-note [linstor] Fix DRBD resources stuck in StandAlone state after reboot and encrypted resource deletion issues ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Prevents duplicate TCP port conflicts after disk toggle operations * Fixes resources stuck in StandAlone or Unknown state after reboot * Resolves issues with encrypted resource deletion * Improves handling of temporarily inaccessible storage devices <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
commit
ea6ec3e5eb
3 changed files with 258 additions and 27 deletions
|
|
@ -8,5 +8,7 @@ Custom patches for piraeus-server (linstor-server) v1.32.3.
|
|||
- Upstream: [#475](https://github.com/LINBIT/linstor-server/pull/475)
|
||||
- **force-metadata-check-on-disk-add.diff** — Create metadata during toggle-disk from diskless to diskful
|
||||
- Upstream: [#474](https://github.com/LINBIT/linstor-server/pull/474)
|
||||
- **skip-adjust-when-device-inaccessible.diff** — Skip DRBD adjust/res file regeneration when child layer device is inaccessible
|
||||
- Upstream: [#471](https://github.com/LINBIT/linstor-server/pull/471)
|
||||
- **fix-duplicate-tcp-ports.diff** — Prevent duplicate TCP ports after toggle-disk operations
|
||||
- Upstream: [#476](https://github.com/LINBIT/linstor-server/pull/476)
|
||||
- **skip-adjust-when-device-inaccessible.diff** — Fix resources stuck in StandAlone after reboot, Unknown state race condition, and encrypted resource deletion
|
||||
- Upstream: [#477](https://github.com/LINBIT/linstor-server/pull/477)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
From 1250abe99d64a0501795e37d3b6af62410002239 Mon Sep 17 00:00:00 2001
|
||||
From: Andrei Kvapil <kvapss@gmail.com>
|
||||
Date: Mon, 12 Jan 2026 13:44:46 +0100
|
||||
Subject: [PATCH] fix(drbd): prevent duplicate TCP ports after toggle-disk
|
||||
operations
|
||||
|
||||
Remove redundant ensureStackDataExists() call with empty payload from
|
||||
resetStoragePools() method that was causing TCP port conflicts after
|
||||
toggle-disk operations.
|
||||
|
||||
Root Cause:
|
||||
-----------
|
||||
The resetStoragePools() method, introduced in 2019 (commit 95cc17d0b8),
|
||||
calls ensureStackDataExists() with an empty LayerPayload. This worked
|
||||
correctly when TCP ports were stored at RscDfn level.
|
||||
|
||||
After the TCP port migration to per-node level (commit f754943463, May
|
||||
2025), this empty payload results in DrbdRscData being created without
|
||||
TCP ports assigned. The controller then sends a Pojo with an empty port
|
||||
Set to satellites.
|
||||
|
||||
On satellites, when DrbdRscData is initialized with an empty port list,
|
||||
initPorts() uses preferredNewPortsRef from peer resources. Since
|
||||
SatelliteDynamicNumberPool.tryAllocate() always returns true (no-op),
|
||||
any port from preferredNewPortsRef is accepted without conflict checking,
|
||||
leading to duplicate TCP port assignments.
|
||||
|
||||
Impact:
|
||||
-------
|
||||
This regression affects toggle-disk operations, particularly:
|
||||
- Snapshot creation/restore operations
|
||||
- Manual toggle-disk operations
|
||||
- Any operation calling resetStoragePools()
|
||||
|
||||
Symptoms include:
|
||||
- DRBD resources failing to adjust with "port is also used" errors
|
||||
- Resources stuck in StandAlone or Connecting states
|
||||
- Multiple resources on the same node using identical TCP ports
|
||||
|
||||
Solution:
|
||||
---------
|
||||
Remove the ensureStackDataExists() call from resetStoragePools() as it
|
||||
is redundant. The calling code (e.g., CtrlRscToggleDiskApiCallHandler
|
||||
line 1071) already invokes ensureStackDataExists() with the correct
|
||||
payload immediately after resetStoragePools().
|
||||
|
||||
This fix ensures:
|
||||
1. resetStoragePools() only resets storage pool assignments
|
||||
2. Layer data creation with proper TCP ports happens via the caller's
|
||||
ensureStackDataExists() with correct payload
|
||||
3. No DrbdRscData objects are created without TCP port assignments
|
||||
|
||||
Related Issues:
|
||||
---------------
|
||||
Fixes #454 - Duplicate TCP ports after backup/restore operations
|
||||
Related to user reports of resources stuck in StandAlone after node
|
||||
reboots when toggle-disk or backup operations were in progress.
|
||||
|
||||
Testing:
|
||||
--------
|
||||
Verified that:
|
||||
- Toggle-disk operations no longer create resources without TCP ports
|
||||
- Backup/restore operations complete without TCP port conflicts
|
||||
- Resources maintain unique TCP ports across toggle-disk cycles
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
|
||||
---
|
||||
.../linbit/linstor/layer/resource/CtrlRscLayerDataFactory.java | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/controller/src/main/java/com/linbit/linstor/layer/resource/CtrlRscLayerDataFactory.java b/controller/src/main/java/com/linbit/linstor/layer/resource/CtrlRscLayerDataFactory.java
|
||||
index 3538b380c..4f589145e 100644
|
||||
--- a/controller/src/main/java/com/linbit/linstor/layer/resource/CtrlRscLayerDataFactory.java
|
||||
+++ b/controller/src/main/java/com/linbit/linstor/layer/resource/CtrlRscLayerDataFactory.java
|
||||
@@ -276,8 +276,6 @@ public class CtrlRscLayerDataFactory
|
||||
|
||||
rscDataToProcess.addAll(rscData.getChildren());
|
||||
}
|
||||
-
|
||||
- ensureStackDataExists(rscRef, null, new LayerPayload());
|
||||
}
|
||||
catch (AccessDeniedException exc)
|
||||
{
|
||||
--
|
||||
2.39.5 (Apple Git-154)
|
||||
|
||||
|
|
@ -1,30 +1,27 @@
|
|||
diff --git a/satellite/src/main/java/com/linbit/linstor/core/devmgr/DeviceHandlerImpl.java b/satellite/src/main/java/com/linbit/linstor/core/devmgr/DeviceHandlerImpl.java
|
||||
index abc123def..def456abc 100644
|
||||
--- a/satellite/src/main/java/com/linbit/linstor/core/devmgr/DeviceHandlerImpl.java
|
||||
+++ b/satellite/src/main/java/com/linbit/linstor/core/devmgr/DeviceHandlerImpl.java
|
||||
@@ -83,6 +83,8 @@ import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Function;
|
||||
+import java.nio.file.Files;
|
||||
+import java.nio.file.Paths;
|
||||
From 6a556821b9a0996d34389a27b941694ce810a44c Mon Sep 17 00:00:00 2001
|
||||
From: Andrei Kvapil <kvapss@gmail.com>
|
||||
Date: Mon, 12 Jan 2026 14:26:57 +0100
|
||||
Subject: [PATCH 1/3] Fix: Skip DRBD adjust/res file regeneration when child
|
||||
layer device is inaccessible
|
||||
|
||||
When deleting encrypted (LUKS) resources, the LUKS layer may close its device
|
||||
before the DRBD layer attempts to adjust the resource or regenerate the res
|
||||
file. This causes 'Failed to adjust DRBD resource' errors.
|
||||
|
||||
This fix adds checks before regenerateResFile() and drbdUtils.adjust()
|
||||
to verify that child layer devices are accessible. If a child device doesn't
|
||||
exist or is not accessible (e.g., LUKS device is closed during resource
|
||||
deletion), these operations are skipped and the adjustRequired flag is cleared,
|
||||
allowing resource deletion to proceed successfully.
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
|
||||
---
|
||||
.../linbit/linstor/layer/drbd/DrbdLayer.java | 72 ++++++++++++++++---
|
||||
1 file changed, 61 insertions(+), 11 deletions(-)
|
||||
|
||||
@Singleton
|
||||
public class DeviceHandlerImpl implements DeviceHandler
|
||||
@@ -1646,7 +1648,10 @@ public class DeviceHandlerImpl implements DeviceHandler
|
||||
private void updateDiscGran(VlmProviderObject<Resource> vlmData) throws DatabaseException, StorageException
|
||||
{
|
||||
String devicePath = vlmData.getDevicePath();
|
||||
- if (devicePath != null && vlmData.exists())
|
||||
+ // Check if device path physically exists before calling lsblk
|
||||
+ // This is important for DRBD devices which might be temporarily unavailable during adjust
|
||||
+ // (drbdadm adjust brings devices down/up, and kernel might not have created the device node yet)
|
||||
+ if (devicePath != null && vlmData.exists() && Files.exists(Paths.get(devicePath)))
|
||||
{
|
||||
if (vlmData.getDiscGran() == VlmProviderObject.UNINITIALIZED_SIZE)
|
||||
{
|
||||
diff --git a/satellite/src/main/java/com/linbit/linstor/layer/drbd/DrbdLayer.java b/satellite/src/main/java/com/linbit/linstor/layer/drbd/DrbdLayer.java
|
||||
index 01967a3..871d830 100644
|
||||
index 01967a31f..871d830d1 100644
|
||||
--- a/satellite/src/main/java/com/linbit/linstor/layer/drbd/DrbdLayer.java
|
||||
+++ b/satellite/src/main/java/com/linbit/linstor/layer/drbd/DrbdLayer.java
|
||||
@@ -592,7 +592,29 @@ public class DrbdLayer implements DeviceLayer
|
||||
|
|
@ -116,3 +113,148 @@ index 01967a3..871d830 100644
|
|||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.39.5 (Apple Git-154)
|
||||
|
||||
|
||||
From afe51ea674c4a350c27d1f2cacfecf6fe42b8a7a Mon Sep 17 00:00:00 2001
|
||||
From: Andrei Kvapil <kvapss@gmail.com>
|
||||
Date: Mon, 12 Jan 2026 14:27:52 +0100
|
||||
Subject: [PATCH 2/3] fix(satellite): skip lsblk when device path doesn't
|
||||
physically exist
|
||||
|
||||
Add physical device path existence check before calling lsblk in updateDiscGran().
|
||||
This prevents race condition when drbdadm adjust temporarily brings devices down/up
|
||||
and the kernel hasn't created the device node yet.
|
||||
|
||||
Issue: After satellite restart with patched code, some DRBD resources ended up in
|
||||
Unknown state because:
|
||||
1. drbdadm adjust successfully completes (brings devices up)
|
||||
2. updateDiscGran() immediately tries to check discard granularity
|
||||
3. /dev/drbd* device node doesn't exist yet (kernel hasn't created it)
|
||||
4. lsblk fails with exit code 32 "not a block device"
|
||||
5. StorageException interrupts DeviceManager cycle
|
||||
6. DRBD device remains in incomplete state
|
||||
|
||||
Solution: Check Files.exists(devicePath) before calling lsblk. If device doesn't
|
||||
exist yet, skip the check - it will be retried in the next DeviceManager cycle
|
||||
when the device node is available.
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
|
||||
---
|
||||
.../linbit/linstor/core/devmgr/DeviceHandlerImpl.java | 9 +++++++--
|
||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/satellite/src/main/java/com/linbit/linstor/core/devmgr/DeviceHandlerImpl.java b/satellite/src/main/java/com/linbit/linstor/core/devmgr/DeviceHandlerImpl.java
|
||||
index 49138a8fd..1c13cfc9d 100644
|
||||
--- a/satellite/src/main/java/com/linbit/linstor/core/devmgr/DeviceHandlerImpl.java
|
||||
+++ b/satellite/src/main/java/com/linbit/linstor/core/devmgr/DeviceHandlerImpl.java
|
||||
@@ -68,6 +68,8 @@ import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
+import java.nio.file.Files;
|
||||
+import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -1645,8 +1647,11 @@ public class DeviceHandlerImpl implements DeviceHandler
|
||||
|
||||
private void updateDiscGran(VlmProviderObject<Resource> vlmData) throws DatabaseException, StorageException
|
||||
{
|
||||
- String devicePath = vlmData.getDevicePath();
|
||||
- if (devicePath != null && vlmData.exists())
|
||||
+ @Nullable String devicePath = vlmData.getDevicePath();
|
||||
+ // Check if device path physically exists before calling lsblk
|
||||
+ // This is important for DRBD devices which might be temporarily unavailable during adjust
|
||||
+ // (drbdadm adjust brings devices down/up, and kernel might not have created the device node yet)
|
||||
+ if (devicePath != null && vlmData.exists() && Files.exists(Paths.get(devicePath)))
|
||||
{
|
||||
if (vlmData.getDiscGran() == VlmProviderObject.UNINITIALIZED_SIZE)
|
||||
{
|
||||
--
|
||||
2.39.5 (Apple Git-154)
|
||||
|
||||
|
||||
From de1f22e7c008c5479f85a3b1ebdf8461944210f4 Mon Sep 17 00:00:00 2001
|
||||
From: Andrei Kvapil <kvapss@gmail.com>
|
||||
Date: Mon, 12 Jan 2026 14:28:23 +0100
|
||||
Subject: [PATCH 3/3] fix(drbd): only check child devices when disk access is
|
||||
actually needed
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The previous implementation blocked `drbdadm adjust` whenever child
|
||||
device paths were unavailable, even for operations that don't require
|
||||
disk access (like network reconnect from StandAlone to Connected).
|
||||
|
||||
After node reboot, DRBD resources often remain in StandAlone state
|
||||
because:
|
||||
1. updateResourceToCurrentDrbdState() correctly detects StandAlone
|
||||
and sets adjustRequired=true
|
||||
2. However, canAdjust check fails because child volumes may have
|
||||
devicePath=null (due to INACTIVE flag, cloning state, or
|
||||
initialization race)
|
||||
3. adjust is skipped → adjustRequired=false → resources stay StandAlone
|
||||
|
||||
Root cause: The canAdjust check was added to protect LUKS deletion
|
||||
scenarios but was applied to ALL cases, including network reconnect
|
||||
which doesn't need disk access.
|
||||
|
||||
Fix: Check child device accessibility only when disk access is actually
|
||||
required (volume creation, resize, metadata operations). Network
|
||||
reconnect operations (StandAlone → Connected) now proceed without
|
||||
checking child devices.
|
||||
|
||||
This ensures automatic DRBD reconnection after reboot while preserving
|
||||
protection for LUKS deletion scenarios.
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
|
||||
---
|
||||
.../linbit/linstor/layer/drbd/DrbdLayer.java | 27 ++++++++++++++++++-
|
||||
1 file changed, 26 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/satellite/src/main/java/com/linbit/linstor/layer/drbd/DrbdLayer.java b/satellite/src/main/java/com/linbit/linstor/layer/drbd/DrbdLayer.java
|
||||
index 871d830d1..78b8195a4 100644
|
||||
--- a/satellite/src/main/java/com/linbit/linstor/layer/drbd/DrbdLayer.java
|
||||
+++ b/satellite/src/main/java/com/linbit/linstor/layer/drbd/DrbdLayer.java
|
||||
@@ -792,7 +792,32 @@ public class DrbdLayer implements DeviceLayer
|
||||
// This is important for encrypted resources (LUKS) where the device
|
||||
// might be closed during deletion
|
||||
boolean canAdjust = true;
|
||||
- if (!skipDisk && !drbdRscData.getAbsResource().isDrbdDiskless(workerCtx))
|
||||
+
|
||||
+ // IMPORTANT: Check child volumes only when disk access is actually needed.
|
||||
+ // For network reconnect (StandAlone -> Connected), disk access is not required.
|
||||
+ boolean needsDiskAccess = false;
|
||||
+
|
||||
+ // Check if there are pending operations that require disk access
|
||||
+ for (DrbdVlmData<Resource> drbdVlmData : drbdRscData.getVlmLayerObjects().values())
|
||||
+ {
|
||||
+ Volume vlm = (Volume) drbdVlmData.getVolume();
|
||||
+ StateFlags<Volume.Flags> vlmFlags = vlm.getFlags();
|
||||
+
|
||||
+ // Disk access is needed if:
|
||||
+ // - creating a new volume
|
||||
+ // - resizing
|
||||
+ // - checking/creating metadata
|
||||
+ if (!drbdVlmData.exists() ||
|
||||
+ drbdVlmData.checkMetaData() ||
|
||||
+ vlmFlags.isSomeSet(workerCtx, Volume.Flags.RESIZE, Volume.Flags.DRBD_RESIZE))
|
||||
+ {
|
||||
+ needsDiskAccess = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Check child volumes only if disk access is actually needed
|
||||
+ if (needsDiskAccess && !skipDisk && !drbdRscData.getAbsResource().isDrbdDiskless(workerCtx))
|
||||
{
|
||||
AbsRscLayerObject<Resource> dataChild = drbdRscData.getChildBySuffix(RscLayerSuffixes.SUFFIX_DATA);
|
||||
if (dataChild != null)
|
||||
--
|
||||
2.39.5 (Apple Git-154)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue