fix(atlas-lib): prune stale LVM device entries on force-released teardown - #545
Closed
boddumanohar wants to merge 1 commit into
Closed
boddumanohar wants to merge 1 commit into
boddumanohar wants to merge 1 commit into
Conversation
…down When a volume group's backing device disappears without a clean unstage, lvmVolumeGroup.Release already falls back to removing the orphaned device-mapper nodes directly. Nothing prunes the matching entry in this host's LVM devices file (/etc/lvm/devices/system.devices), so a node accumulates one stale entry per failure cycle over its lifetime. Add Manager.ForgetDevice (lvmdevices --deldev, scoped to the device) and call it from the same force path, once per device the layer was handed. It's best-effort: a failure is logged, not propagated, since this is hygiene and must never turn a routine unstage into a failed one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
boddumanohar
added a commit
that referenced
this pull request
Sep 16, 2026
…#277) Implements design-issue-277-client-side-compression.md against current main rather than rebasing the abandoned PR #402 branch, which predates the csi-driver restructuring (#497), the v1alpha2 CRD redesign, and the SimplyblockDriver-managed DaemonSet (#513). Built on atlas-lib/volstack's three LVM layers per the user's request, in place of PR #402's flat atlas-lib/lvm/vdo package, which retires here with zero importers. - atlas-lib/lvm: a built-in "vdo" VolumeProvisioning handler, registered by the package's own init (the registry existed with nothing real registered against it — CreateLogicalVolume silently dropped compression/deduplication before this). Manager.ForgetDevice/HasOrphanedDMNodes, new lvmdevices/ dmsetup primitives. - atlas-lib/volstack/layers: lvmPhysicalVolume, lvmVolumeGroup, and lvmLogicalVolume now tolerate total path loss (the member device gone entirely, not merely unreadable) without erroring the whole Down walk; lvmVolumeGroup.Release forgets stale system.devices entries (folds in the still-open PR #545). - atlas-lib/kube: client_compression/client_deduplication StorageClass parameters, storage.simplyblock.io/vdo-capable label and its managed-by annotation, the shared vdo-capable marker path. - operator: VolumeDefaults.EnableClientCompression/EnableClientDeduplication (v1alpha2), threaded through ClassParameters and the v1alpha1 conversion's hub-only stash; the csi-node DaemonSet's postStart hook probes dm-vdo alongside its existing nvme-tcp/nvme-rdma modprobes (no hostPID needed — the existing probes already prove that), with RBAC to self-label. - csi-driver: vdoCapableSegment (twin of dhchapAllowedNodeSegment) pins PV nodeAffinity from CreateVolume, deliberately not via StorageClass AllowedTopologies — that mechanism was found broken for DHCHAP and removed in PR #484, for a reason that applies identically to a self-probed capability label. A rawDeviceLayer adapter lets the three LVM layers run through the real volstack.Runner without adopting fabric/filesystem (Phase 1, unrelated, unwired work), wired into NodeStageVolume/ NodeUnstageVolume/restageVolume/NodeExpandVolume only for volumes that request either parameter. - Dockerfile_base: the vdo package (vdoformat), x86_64 only. Deviations from the merged design are called out inline in the doc's 2026-09-16 revision notes (§5, §7.1, §4.1, Q9). Not implemented, matching the design's own already-open items: the zero-capable-node pool event (§5.1, Q13), CSI metrics (§13, Q6), the SetFeatures live-toggle path (Q1), the PVC-size floor admission webhook (Q2, despite the doc's stale "Resolved" note — no such webhook exists on main), and periodic capability re-checking (Q12). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Member
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Q5 in
design-issue-277-client-side-compression.md: the node's LVM devices file (/etc/lvm/devices/system.devices, which restricts LVM's default device visibility) never gets pruned after a device disappears, so a node accumulates one stale entry per failure cycle over its lifetime.lvmVolumeGroup.Release(atlas-lib/volstack/layers/lvmvolumegroup.go) already has the right force path for this: whenvgchange -anfails because the backing device vanished without a clean unstage, it falls back to removing the orphaned device-mapper nodes directly (Manager.RemoveOrphanedDMNodes). That's exactly where the stalesystem.devicesentry is also known to be stale, so this adds the pruning step there.Changes
Manager.ForgetDevice(atlas-lib/lvm/devices.go): a new primitive,lvmdevices --deldev <path>, scoped to the device the same wayCreatePhysicalVolume/RemovePhysicalVolumeare.lvmVolumeGroup.Releasenow calls it, once per device it was handed, after falling back to the device-mapper cleanup. It's best-effort: a failure is logged (warnf, matchingatlas-lib/lvm/vdo's ownLoggerconvention, introduced here forvolstack/layerssince it didn't have one yet) and does not failRelease— this is hygiene, and it must never turn a routine unstage into a failed one.Testing
Followed this repo's red-first workflow: added
TestManager_ForgetDeviceandTestLVMVolumeGroupReleaseForgetsDevicesOnTheForcePathfirst, confirmed both failed (the first on a missing method, the second because the layer'sReleasedidn't call it yet), then implemented.go test -race ./lvm/... ./volstack/...— all green, including a new test thatReleasestill succeeds whenForgetDeviceitself errors.golangci-lint run ./lvm/... ./volstack/...— 0 issues.make testfails locally, but on an unrelated, pre-existing issue: itsvettarget pulls in abuf-generated dependency chain that tries to fetchgithub.com/google/cel-goand the environment here can't reach it. Not something this change touches.One thing worth flagging before merge: I don't have
lvm2/lvmdevicesavailable in this environment, so I could not verify against a real system whatlvmdevices --deldevactually prints when a device isn't in the devices file.ForgetDevicedoesn't special-case that (noisNoXxx-style error matching, unlike this package's other idempotency helpers), and the caller inReleasetreats any failure as best-effort/logged rather than fatal, specifically to sidestep needing to know that exact text. Worth a quick live check before this ships, the way this package's otherisNoXxxhelpers were confirmed against a real cluster.Out of scope, flagged separately
While reading
fabric.gofor this,ObservereturnsStateAbsentwith an emptyArtifact{}when a device has vanished from the kernel entirely (not just unreachable).lvmPhysicalVolume.ObserveandlvmVolumeGroup.Observeboth hard-error on zero devices below them ("the layer below exposes no device[s] to..."), andDown'ssurvey()aborts on the firstObserveerror. That would mean a total, complete device loss on a volume with an LVM stack fails teardown outright, rather than reaching the force path this PR extends — which seems to work againstdesign-node-volume-stack.md§7.4's stated goal that bring-down "tolerates a dead foundation." Not verified against a live cluster, not fixed here — a separate investigation.🤖 Generated with Claude Code