carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package host
4
5import (
6 "fmt"
7 "os"
8 "path/filepath"
9 "strings"
10
11 "github.com/carlosframework/platform/internal/hostbox"
12 "golang.org/x/sys/unix"
13)
14
15// Resolve the filesystem's kernel device, then its containing disk if it is a
16// partition. Only an EBS NVMe controller serial supplies independent identity;
17// filesystem UUIDs and loop backing files cannot distinguish snapshot clones.
18func servingParkVolume(device uint64) string {
19 return servingParkVolumeAt("/sys", device)
20}
21
22func servingParkVolumeAt(sys string, device uint64) string {
23 path, err := filepath.EvalSymlinks(filepath.Join(sys, "dev", "block", fmt.Sprintf("%d:%d", unix.Major(device), unix.Minor(device))))
24 if err != nil {
25 return ""
26 }
27 if _, err := os.Stat(filepath.Join(path, "partition")); err == nil {
28 path = filepath.Dir(path)
29 } else if !os.IsNotExist(err) {
30 return ""
31 }
32 raw, err := os.ReadFile(filepath.Join(path, "device", "serial"))
33 if err != nil {
34 return ""
35 }
36 serial := strings.TrimSpace(string(raw))
37 if !strings.HasPrefix(serial, "vol") {
38 return ""
39 }
40 id := strings.TrimPrefix(strings.TrimPrefix(serial, "vol"), "-")
41 if len(id) != 8 && len(id) != 17 {
42 return ""
43 }
44 for _, c := range id {
45 if !(c >= '0' && c <= '9' || c >= 'a' && c <= 'f') {
46 return ""
47 }
48 }
49 return "vol" + id
50}
51
52// A reboot binding grants recovery but never supplies missing volume evidence.
53// Check again at deletion so a subsequent reboot or remount cannot borrow it.
54func (f *servingParkFS) checkReapVolume(r *servingParkRecord) error {
55 b, err := servingParkReadBinding(f.state, "retirement-"+r.Authorization.ID)
56 if err != nil {
57 return err
58 }
59 if b == nil {
60 return nil
61 }
62 if f.volume == nil || b.Volume == "" || b.Volume != r.Source.Volume || f.volume(r.Source.Parent.Device) != r.Source.Volume {
63 return hostbox.ErrChanged
64 }
65 return f.checkBoot(b.BootID)
66}
67