diff options
| author | Eric Biggers <ebiggers@google.com> | 2019-10-29 00:04:39 -0700 |
|---|---|---|
| committer | Eric Biggers <ebiggers@google.com> | 2019-10-30 09:11:29 -0700 |
| commit | fe58e7236a3285e172733aeab0b136bec968ac4d (patch) | |
| tree | 35dce6e49541c05c5a5713ba7af3f20fe0d8dd24 /filesystem/mountpoint.go | |
| parent | c7da2443d6ffa51727db09f8ef1df6aea8c7612c (diff) | |
filesystem: make link handling more robust
The previous patch fixed making linked protectors to /dev/root, by
setting Mount.Device to the real device node rather than /dev/root.
That's good, but it also hints that the linked protector handling is
unnecessarily fragile, as it relies on the device node name matching
exactly. The Linux kernel allows the same device to have multiple
device nodes, and path comparisons are slow and error-prone in general.
Change it to compare the device number instead.
Diffstat (limited to 'filesystem/mountpoint.go')
| -rw-r--r-- | filesystem/mountpoint.go | 26 |
1 files changed, 12 insertions, 14 deletions
diff --git a/filesystem/mountpoint.go b/filesystem/mountpoint.go index da6a69a..d40f864 100644 --- a/filesystem/mountpoint.go +++ b/filesystem/mountpoint.go @@ -39,7 +39,7 @@ import ( var ( // These maps hold data about the state of the system's mountpoints. mountsByPath map[string]*Mount - mountsByDevice map[string][]*Mount + mountsByDevice map[DeviceNumber][]*Mount // Used to make the mount functions thread safe mountMutex sync.Mutex // True if the maps have been successfully initialized. @@ -135,7 +135,7 @@ func loadMountInfo() error { return nil } mountsByPath = make(map[string]*Mount) - mountsByDevice = make(map[string][]*Mount) + mountsByDevice = make(map[DeviceNumber][]*Mount) file, err := os.Open("/proc/self/mountinfo") if err != nil { @@ -162,9 +162,7 @@ func loadMountInfo() error { // filesystems are listed in mount order. mountsByPath[mnt.Path] = mnt - if mnt.Device != "" { - mountsByDevice[mnt.Device] = append(mountsByDevice[mnt.Device], mnt) - } + mountsByDevice[mnt.DeviceNumber] = append(mountsByDevice[mnt.DeviceNumber], mnt) } mountsInitialized = true return nil @@ -277,7 +275,7 @@ func getMountsFromLink(link string) ([]*Mount, error) { if filepath.Base(searchPath) != value { return nil, errors.Wrapf(ErrFollowLink, "value %q is not a UUID", value) } - devicePath, err := canonicalizePath(searchPath) + deviceNumber, err := getDeviceNumber(searchPath) if err != nil { return nil, errors.Wrapf(ErrFollowLink, "no device with UUID %q", value) } @@ -288,9 +286,11 @@ func getMountsFromLink(link string) ([]*Mount, error) { if err := loadMountInfo(); err != nil { return nil, err } - mnts, ok := mountsByDevice[devicePath] + mnts, ok := mountsByDevice[deviceNumber] if !ok { - return nil, errors.Wrapf(ErrFollowLink, "no mounts for device %q", devicePath) + devicePath, _ := canonicalizePath(searchPath) + return nil, errors.Wrapf(ErrFollowLink, "no mounts for device %q (%v)", + devicePath, deviceNumber) } return mnts, nil } @@ -302,9 +302,6 @@ func makeLink(mnt *Mount, token string) (string, error) { if token != uuidToken { return "", errors.Wrapf(ErrMakeLink, "token type %q not supported", token) } - if mnt.Device == "" { - return "", errors.Wrapf(ErrMakeLink, "no device for mount %q", mnt.Path) - } dirContents, err := ioutil.ReadDir(uuidDirectory) if err != nil { @@ -315,14 +312,15 @@ func makeLink(mnt *Mount, token string) (string, error) { continue // Only interested in UUID symlinks } uuid := fileInfo.Name() - devicePath, err := canonicalizePath(filepath.Join(uuidDirectory, uuid)) + deviceNumber, err := getDeviceNumber(filepath.Join(uuidDirectory, uuid)) if err != nil { log.Print(err) continue } - if mnt.Device == devicePath { + if mnt.DeviceNumber == deviceNumber { return fmt.Sprintf("%s=%s", uuidToken, uuid), nil } } - return "", errors.Wrapf(ErrMakeLink, "device %q has no UUID", mnt.Device) + return "", errors.Wrapf(ErrMakeLink, "device %q (%v) has no UUID", + mnt.Device, mnt.DeviceNumber) } |