//go:build linux package host import ( "fmt" "os" "path/filepath" "strings" "github.com/carlosframework/platform/internal/hostbox" "golang.org/x/sys/unix" ) // Resolve the filesystem's kernel device, then its containing disk if it is a // partition. Only an EBS NVMe controller serial supplies independent identity; // filesystem UUIDs and loop backing files cannot distinguish snapshot clones. func servingParkVolume(device uint64) string { return servingParkVolumeAt("/sys", device) } func servingParkVolumeAt(sys string, device uint64) string { path, err := filepath.EvalSymlinks(filepath.Join(sys, "dev", "block", fmt.Sprintf("%d:%d", unix.Major(device), unix.Minor(device)))) if err != nil { return "" } if _, err := os.Stat(filepath.Join(path, "partition")); err == nil { path = filepath.Dir(path) } else if !os.IsNotExist(err) { return "" } raw, err := os.ReadFile(filepath.Join(path, "device", "serial")) if err != nil { return "" } serial := strings.TrimSpace(string(raw)) if !strings.HasPrefix(serial, "vol") { return "" } id := strings.TrimPrefix(strings.TrimPrefix(serial, "vol"), "-") if len(id) != 8 && len(id) != 17 { return "" } for _, c := range id { if !(c >= '0' && c <= '9' || c >= 'a' && c <= 'f') { return "" } } return "vol" + id } // A reboot binding grants recovery but never supplies missing volume evidence. // Check again at deletion so a subsequent reboot or remount cannot borrow it. func (f *servingParkFS) checkReapVolume(r *servingParkRecord) error { b, err := servingParkReadBinding(f.state, "retirement-"+r.Authorization.ID) if err != nil { return err } if b == nil { return nil } if f.volume == nil || b.Volume == "" || b.Volume != r.Source.Volume || f.volume(r.Source.Parent.Device) != r.Source.Volume { return hostbox.ErrChanged } return f.checkBoot(b.BootID) }