From f7518078a3160bf2d47625db63654fa414461190 Mon Sep 17 00:00:00 2001 From: Vasu Mahalingam Date: Wed, 4 Jun 2025 08:22:00 +0000 Subject: [PATCH] Fix: PVC finalizer not removed due to broken VolumeSnapshots When VolumeSnapshots referencing a PVC are stuck in a non-ready state (e.g., due to a misconfigured VolumeSnapshotClass), the PVC finalizer \`pvc-as-source-protection\` is never removed, preventing PVC deletion. This patch ensures that only VolumeSnapshots that are: - not ReadyToUse - and still own the PVC finalizer are considered \"in-use\" by the snapshot controller. This prevents invalid or broken snapshots from blocking PVC deletion. Signed-off-by: Vasu Mahalingam --- pkg/common-controller/snapshot_controller.go | 7 ++++++- pkg/utils/util.go | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/pkg/common-controller/snapshot_controller.go b/pkg/common-controller/snapshot_controller.go index 732e617d5..8177e82c7 100644 --- a/pkg/common-controller/snapshot_controller.go +++ b/pkg/common-controller/snapshot_controller.go @@ -1050,7 +1050,12 @@ func (ctrl *csiSnapshotCommonController) isPVCBeingUsed(pvc *v1.PersistentVolume klog.V(4).Infof("Skipping static bound snapshot %s when checking PVC %s/%s", snap.Name, pvc.Namespace, pvc.Name) continue } - if snap.Spec.Source.PersistentVolumeClaimName != nil && pvc.Name == *snap.Spec.Source.PersistentVolumeClaimName && !utils.IsSnapshotReady(snap) { + + if snap.Spec.Source.PersistentVolumeClaimName != nil && + pvc.Name == *snap.Spec.Source.PersistentVolumeClaimName && + !utils.IsSnapshotReady(snap) && + utils.HasSnapshotFinalizer(snap, utils.PVCFinalizer) { + klog.V(2).Infof("Keeping PVC %s/%s, it is used by snapshot %s/%s", pvc.Namespace, pvc.Name, snap.Namespace, snap.Name) return true } diff --git a/pkg/utils/util.go b/pkg/utils/util.go index f4f82b34a..d80d9ca9d 100644 --- a/pkg/utils/util.go +++ b/pkg/utils/util.go @@ -611,6 +611,15 @@ func IsBoundVolumeSnapshotContentNameSet(snapshot *crdv1.VolumeSnapshot) bool { return true } +func HasSnapshotFinalizer(snapshot *crdv1.VolumeSnapshot, finalizer string) bool { + for _, f := range snapshot.ObjectMeta.Finalizers { + if f == finalizer { + return true + } + } + return false +} + func IsSnapshotReady(snapshot *crdv1.VolumeSnapshot) bool { if snapshot.Status == nil || snapshot.Status.ReadyToUse == nil || *snapshot.Status.ReadyToUse == false { return false