From c0febb0b49fe8bf950a7bea378aca4ac39912e6d Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Tue, 6 Jan 2026 09:25:56 +0100 Subject: [PATCH] fix(drbd): create metadata during toggle-disk from diskless to diskful When a diskless resource is being converted to diskful via toggle-disk, several conditions prevented DRBD metadata from being created: 1. processChild() didn't process child layers for diskless resources during disk addition 2. detachVolumesIfNecessary() returned empty checkMetaData list for diskless resources 3. Metadata creation block was skipped for diskless resources 4. hasMetaData() assumed metadata exists when hasDisk() returns true, even during retry when storage exists but no metadata This caused toggle-disk to fail with "No valid meta data found" error from drbdadm adjust, especially for LUKS encrypted resources. Add DISK_ADD_REQUESTED/DISK_ADDING flag checks to: - Process child layers during toggle-disk - Include volumes in metadata check list - Enter metadata creation block - Force metadata verification during retry Co-Authored-By: Claude Signed-off-by: Andrei Kvapil --- .../linbit/linstor/layer/drbd/DrbdLayer.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) 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 31d9b5c56..c1f2cd2e5 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 @@ -501,10 +501,13 @@ private boolean processChild( boolean isDiskless = drbdRscData.getAbsResource().isDrbdDiskless(workerCtx); StateFlags rscFlags = drbdRscData.getAbsResource().getStateFlags(); boolean isDiskRemoving = rscFlags.isSet(workerCtx, Resource.Flags.DISK_REMOVING); + // Check if we're in toggle-disk operation (adding disk to diskless resource) + boolean isDiskAdding = rscFlags.isSomeSet(workerCtx, Resource.Flags.DISK_ADD_REQUESTED, Resource.Flags.DISK_ADDING); boolean contProcess = isDiskless; - boolean processChildren = !isDiskless || isDiskRemoving; + // Process children when: has disk, removing disk, OR adding disk (toggle-disk) + boolean processChildren = !isDiskless || isDiskRemoving || isDiskAdding; // do not process children when ONLY DRBD_DELETE flag is set (DELETE flag is still unset) processChildren &= (!rscFlags.isSet(workerCtx, Resource.Flags.DRBD_DELETE) || rscFlags.isSet(workerCtx, Resource.Flags.DELETE)); @@ -697,7 +700,11 @@ else if (isNeitherResizeFlagsSet(drbdVlmData)) { // hasMetaData needs to be run after child-resource processed List> createMetaData = new ArrayList<>(); - if (!drbdRscData.getAbsResource().isDrbdDiskless(workerCtx) && !skipDisk) + // Check if we're in toggle-disk operation (adding disk to diskless resource) + boolean isDiskAddingForMd = drbdRscData.getAbsResource().getStateFlags() + .isSomeSet(workerCtx, Resource.Flags.DISK_ADD_REQUESTED, Resource.Flags.DISK_ADDING); + // Create metadata when: has disk OR adding disk (toggle-disk), and skipDisk is disabled + if ((!drbdRscData.getAbsResource().isDrbdDiskless(workerCtx) || isDiskAddingForMd) && !skipDisk) { // do not try to create meta data while the resource is diskless or skipDisk is enabled for (DrbdVlmData drbdVlmData : checkMetaData) @@ -1114,8 +1121,10 @@ private List> detachVolumesIfNecessary(DrbdRscData> checkMetaData = new ArrayList<>(); Resource rsc = drbdRscData.getAbsResource(); + // Include DISK_ADD_REQUESTED/DISK_ADDING for toggle-disk scenario where we need to check/create metadata if (!rsc.isDrbdDiskless(workerCtx) || - rsc.getStateFlags().isSet(workerCtx, Resource.Flags.DISK_REMOVING) + rsc.getStateFlags().isSet(workerCtx, Resource.Flags.DISK_REMOVING) || + rsc.getStateFlags().isSomeSet(workerCtx, Resource.Flags.DISK_ADD_REQUESTED, Resource.Flags.DISK_ADDING) ) { // using a dedicated list to prevent concurrentModificationException @@ -1311,8 +1320,12 @@ private boolean hasMetaData(DrbdVlmData drbdVlmData) // Assume that meta data is there and do not create meta data if the check is disabled (checkMetaData), // except if there is no disk, because when adding a disk, meta data for a disk must be created - // despite the DRBD logic still saying it is diskless - hasMetaData = !drbdVlmData.checkMetaData() && drbdVlmData.hasDisk(); + // despite the DRBD logic still saying it is diskless. + // Also force metadata check when DISK_ADD_REQUESTED/DISK_ADDING flag is set (retry scenario + // where storage exists but no metadata). + boolean isDiskAddingState = drbdVlmData.getRscLayerObject().getAbsResource().getStateFlags() + .isSomeSet(workerCtx, Resource.Flags.DISK_ADD_REQUESTED, Resource.Flags.DISK_ADDING); + hasMetaData = !drbdVlmData.checkMetaData() && drbdVlmData.hasDisk() && !isDiskAddingState; if (!hasMetaData) { if (mdUtils.hasMetaData())