Use stat_t.st_rdev to compare block devices
I implemented /dev/disk/by-uuid on my platform but using absolute links (where udev typically uses relative) which broke the code in `os.DeviceUUID`. Rather than just patch that up directly instead stat both the target and candidate devices and pick one with matching major:minor in st_rdev. This saves manually building paths to resolve symlinks and I think should be more robust overall. I also removed the initial stat of /dev/disk/by-uuid, I believe `ioutil.Readdir` will correctly return an error if the path does not exist. Signed-off-by: Ian Campbell <ijc@docker.com>
This commit is contained in:
parent
0e6e593481
commit
11714fb6a3
32
pkg/os/os.go
32
pkg/os/os.go
@ -22,6 +22,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
containerdmount "github.com/containerd/containerd/mount"
|
containerdmount "github.com/containerd/containerd/mount"
|
||||||
"github.com/containerd/fifo"
|
"github.com/containerd/fifo"
|
||||||
@ -130,28 +131,41 @@ func (RealOS) LookupMount(path string) (containerdmount.Info, error) {
|
|||||||
return containerdmount.Lookup(path)
|
return containerdmount.Lookup(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// blkdev returns the rdev of a block device or an error if not a block device
|
||||||
|
func blkrdev(device string) (uint64, error) {
|
||||||
|
info, err := os.Stat(device)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
stat := info.Sys().(*syscall.Stat_t)
|
||||||
|
if (stat.Mode & syscall.S_IFMT) != syscall.S_IFBLK {
|
||||||
|
return 0, fmt.Errorf("%s is not a block device", device)
|
||||||
|
}
|
||||||
|
return stat.Rdev, nil
|
||||||
|
}
|
||||||
|
|
||||||
// DeviceUUID gets device uuid of a device. The passed in device should be
|
// DeviceUUID gets device uuid of a device. The passed in device should be
|
||||||
// an absolute path of the device.
|
// an absolute path of the device.
|
||||||
func (RealOS) DeviceUUID(device string) (string, error) {
|
func (RealOS) DeviceUUID(device string) (string, error) {
|
||||||
const uuidDir = "/dev/disk/by-uuid"
|
rdev, err := blkrdev(device)
|
||||||
if _, err := os.Stat(uuidDir); err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uuidDir = "/dev/disk/by-uuid"
|
||||||
files, err := ioutil.ReadDir(uuidDir)
|
files, err := ioutil.ReadDir(uuidDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
path := filepath.Join(uuidDir, file.Name())
|
path := filepath.Join(uuidDir, file.Name())
|
||||||
target, err := os.Readlink(path)
|
|
||||||
|
trdev, err := blkrdev(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
continue
|
||||||
}
|
}
|
||||||
dev, err := filepath.Abs(filepath.Join(uuidDir, target))
|
|
||||||
if err != nil {
|
if rdev == trdev {
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if dev == device {
|
|
||||||
return file.Name(), nil
|
return file.Name(), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user