From 4302ae445a6ae20b06b27f4a550ccfbee8fc0c8b 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 8ae79dfae..d47ee34f8 100644 --- a/pkg/common-controller/snapshot_controller.go +++ b/pkg/common-controller/snapshot_controller.go @@ -961,7 +961,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 9c89d16c7..6c07170f8 100644 --- a/pkg/utils/util.go +++ b/pkg/utils/util.go @@ -484,6 +484,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