From 8cd218237b49b41bffa0035393143571ec01b157 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 10 May 2017 04:53:59 +0000 Subject: [PATCH] mountinfo: refactored Signed-off-by: Akihiro Suda --- mountinfo/mountinfo.go | 17 ++++++----------- mountinfo/mountinfo_freebsd.go | 16 ++++++++++------ mountinfo/mountinfo_linux.go | 23 +++++++++++------------ mountinfo/mountinfo_linux_test.go | 8 ++++---- mountinfo/mountinfo_solaris.go | 16 +++++++++++----- mountinfo/mountinfo_unsupported.go | 12 +++++++++--- mountinfo/mountinfo_windows.go | 6 ------ snapshot/btrfs/btrfs.go | 10 +++++----- snapshot/btrfs/btrfs_test.go | 30 +++++++++++++++--------------- 9 files changed, 71 insertions(+), 67 deletions(-) delete mode 100644 mountinfo/mountinfo_windows.go diff --git a/mountinfo/mountinfo.go b/mountinfo/mountinfo.go index 9f5176599..4bc11badd 100644 --- a/mountinfo/mountinfo.go +++ b/mountinfo/mountinfo.go @@ -23,23 +23,18 @@ type Info struct { // Mountpoint indicates the mount point relative to the process's root. Mountpoint string - // Opts represents mount-specific options. - Opts string + // Options represents mount-specific options. + Options string // Optional represents optional fields. Optional string - // Fstype indicates the type of filesystem, such as EXT3. - Fstype string + // FSType indicates the type of filesystem, such as EXT3. + FSType string // Source indicates filesystem specific information or "none". Source string - // VfsOpts represents per super block options. - VfsOpts string -} - -// GetMounts retrieves a list of mounts for the current running process. -func GetMounts() ([]*Info, error) { - return parseMountTable() + // VFSOptions represents per super block options. + VFSOptions string } diff --git a/mountinfo/mountinfo_freebsd.go b/mountinfo/mountinfo_freebsd.go index 29936716b..ffb37494c 100644 --- a/mountinfo/mountinfo_freebsd.go +++ b/mountinfo/mountinfo_freebsd.go @@ -13,9 +13,8 @@ import ( "unsafe" ) -// Parse /proc/self/mountinfo because comparing Dev and ino does not work from -// bind mounts. -func parseMountTable() ([]*Info, error) { +// Self retrieves a list of mounts for the current running process. +func Self() ([]Info, error) { var rawEntries *C.struct_statfs count := int(C.getmntinfo(&rawEntries, C.MNT_WAIT)) @@ -29,13 +28,18 @@ func parseMountTable() ([]*Info, error) { header.Len = count header.Data = uintptr(unsafe.Pointer(rawEntries)) - var out []*Info + var out []Info for _, entry := range entries { var mountinfo Info mountinfo.Mountpoint = C.GoString(&entry.f_mntonname[0]) mountinfo.Source = C.GoString(&entry.f_mntfromname[0]) - mountinfo.Fstype = C.GoString(&entry.f_fstypename[0]) - out = append(out, &mountinfo) + mountinfo.FSType = C.GoString(&entry.f_fstypename[0]) + out = append(out, mountinfo) } return out, nil } + +// PID collects the mounts for a specific process ID. +func PID(pid int) ([]Info, error) { + return nil, fmt.Errorf("mountinfo.PID is not implemented on freebsd") +} diff --git a/mountinfo/mountinfo_linux.go b/mountinfo/mountinfo_linux.go index 22f2a44ee..6cb08fd80 100644 --- a/mountinfo/mountinfo_linux.go +++ b/mountinfo/mountinfo_linux.go @@ -28,9 +28,8 @@ const ( mountinfoFormat = "%d %d %d:%d %s %s %s %s" ) -// Parse /proc/self/mountinfo because comparing Dev and ino does not work from -// bind mounts -func parseMountTable() ([]*Info, error) { +// Self retrieves a list of mounts for the current running process. +func Self() ([]Info, error) { f, err := os.Open("/proc/self/mountinfo") if err != nil { return nil, err @@ -40,10 +39,10 @@ func parseMountTable() ([]*Info, error) { return parseInfoFile(f) } -func parseInfoFile(r io.Reader) ([]*Info, error) { +func parseInfoFile(r io.Reader) ([]Info, error) { var ( s = bufio.NewScanner(r) - out = []*Info{} + out = []Info{} ) for s.Scan() { @@ -52,14 +51,14 @@ func parseInfoFile(r io.Reader) ([]*Info, error) { } var ( - p = &Info{} + p = Info{} text = s.Text() optionalFields string ) if _, err := fmt.Sscanf(text, mountinfoFormat, &p.ID, &p.Parent, &p.Major, &p.Minor, - &p.Root, &p.Mountpoint, &p.Opts, &optionalFields); err != nil { + &p.Root, &p.Mountpoint, &p.Options, &optionalFields); err != nil { return nil, fmt.Errorf("Scanning '%s' failed: %s", text, err) } // Safe as mountinfo encodes mountpoints with spaces as \040. @@ -73,18 +72,18 @@ func parseInfoFile(r io.Reader) ([]*Info, error) { p.Optional = optionalFields } - p.Fstype = postSeparatorFields[0] + p.FSType = postSeparatorFields[0] p.Source = postSeparatorFields[1] - p.VfsOpts = strings.Join(postSeparatorFields[2:], " ") + p.VFSOptions = strings.Join(postSeparatorFields[2:], " ") out = append(out, p) } return out, nil } -// PidMountInfo collects the mounts for a specific process ID. If the process -// ID is unknown, it is better to use `GetMounts` which will inspect +// PID collects the mounts for a specific process ID. If the process +// ID is unknown, it is better to use `Self` which will inspect // "/proc/self/mountinfo" instead. -func PidMountInfo(pid int) ([]*Info, error) { +func PID(pid int) ([]Info, error) { f, err := os.Open(fmt.Sprintf("/proc/%d/mountinfo", pid)) if err != nil { return nil, err diff --git a/mountinfo/mountinfo_linux_test.go b/mountinfo/mountinfo_linux_test.go index d5fa98da5..9a74eeb0b 100644 --- a/mountinfo/mountinfo_linux_test.go +++ b/mountinfo/mountinfo_linux_test.go @@ -463,14 +463,14 @@ func TestParseFedoraMountinfoFields(t *testing.T) { Minor: 3, Root: "/", Mountpoint: "/proc", - Opts: "rw,nosuid,nodev,noexec,relatime", + Options: "rw,nosuid,nodev,noexec,relatime", Optional: "shared:5", - Fstype: "proc", + FSType: "proc", Source: "proc", - VfsOpts: "rw", + VFSOptions: "rw", } - if *infos[0] != mi { + if infos[0] != mi { t.Fatalf("expected %#v, got %#v", mi, infos[0]) } } diff --git a/mountinfo/mountinfo_solaris.go b/mountinfo/mountinfo_solaris.go index d9f3e0d12..abf8c71db 100644 --- a/mountinfo/mountinfo_solaris.go +++ b/mountinfo/mountinfo_solaris.go @@ -12,13 +12,14 @@ import ( "fmt" ) -func parseMountTable() ([]*Info, error) { +// Self retrieves a list of mounts for the current running process. +func Self() ([]Info, error) { mnttab := C.fopen(C.CString(C.MNTTAB), C.CString("r")) if mnttab == nil { return nil, fmt.Errorf("Failed to open %s", C.MNTTAB) } - var out []*Info + var out []Info var mp C.struct_mnttab ret := C.getmntent(mnttab, &mp) @@ -26,12 +27,17 @@ func parseMountTable() ([]*Info, error) { var mountinfo Info mountinfo.Mountpoint = C.GoString(mp.mnt_mountp) mountinfo.Source = C.GoString(mp.mnt_special) - mountinfo.Fstype = C.GoString(mp.mnt_fstype) - mountinfo.Opts = C.GoString(mp.mnt_mntopts) - out = append(out, &mountinfo) + mountinfo.FSType = C.GoString(mp.mnt_fstype) + mountinfo.Options = C.GoString(mp.mnt_mntopts) + out = append(out, mountinfo) ret = C.getmntent(mnttab, &mp) } C.fclose(mnttab) return out, nil } + +// PID collects the mounts for a specific process ID. +func PID(pid int) ([]Info, error) { + return nil, fmt.Errorf("mountinfo.PID is not implemented on solaris") +} diff --git a/mountinfo/mountinfo_unsupported.go b/mountinfo/mountinfo_unsupported.go index 15f43f07a..1ef75dcae 100644 --- a/mountinfo/mountinfo_unsupported.go +++ b/mountinfo/mountinfo_unsupported.go @@ -1,4 +1,4 @@ -// +build !windows,!linux,!freebsd,!solaris freebsd,!cgo solaris,!cgo +// +build !linux,!freebsd,!solaris freebsd,!cgo solaris,!cgo package mountinfo @@ -7,6 +7,12 @@ import ( "runtime" ) -func parseMountTable() ([]*Info, error) { - return nil, fmt.Errorf("mount.parseMountTable is not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +// Self retrieves a list of mounts for the current running process. +func Self() ([]Info, error) { + return nil, fmt.Errorf("mountinfo.Self is not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +// PID collects the mounts for a specific process ID. +func PID(pid int) ([]Info, error) { + return nil, fmt.Errorf("mountinfo.PID is not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) } diff --git a/mountinfo/mountinfo_windows.go b/mountinfo/mountinfo_windows.go deleted file mode 100644 index 9564ab90f..000000000 --- a/mountinfo/mountinfo_windows.go +++ /dev/null @@ -1,6 +0,0 @@ -package mountinfo - -func parseMountTable() ([]*Info, error) { - // Do NOT return an error! - return nil, nil -} diff --git a/snapshot/btrfs/btrfs.go b/snapshot/btrfs/btrfs.go index fbed3dfbe..a22c48385 100644 --- a/snapshot/btrfs/btrfs.go +++ b/snapshot/btrfs/btrfs.go @@ -36,17 +36,17 @@ type snapshotter struct { ms *storage.MetaStore } -func getBtrfsDevice(root string, mounts []*mountinfo.Info) (string, error) { +func getBtrfsDevice(root string, mounts []mountinfo.Info) (string, error) { device := "" deviceMountpoint := "" for _, info := range mounts { if (info.Root == "/" || info.Root == "") && strings.HasPrefix(root, info.Mountpoint) { - if info.Fstype == "btrfs" && len(info.Mountpoint) > len(deviceMountpoint) { + if info.FSType == "btrfs" && len(info.Mountpoint) > len(deviceMountpoint) { device = info.Source deviceMountpoint = info.Mountpoint } - if root == info.Mountpoint && info.Fstype != "btrfs" { - return "", fmt.Errorf("%s needs to be btrfs, but seems %s", root, info.Fstype) + if root == info.Mountpoint && info.FSType != "btrfs" { + return "", fmt.Errorf("%s needs to be btrfs, but seems %s", root, info.FSType) } } } @@ -62,7 +62,7 @@ func getBtrfsDevice(root string, mounts []*mountinfo.Info) (string, error) { // a file in the provided root. // root needs to be a mount point of btrfs. func NewSnapshotter(root string) (snapshot.Snapshotter, error) { - mounts, err := mountinfo.GetMounts() + mounts, err := mountinfo.Self() if err != nil { return nil, err } diff --git a/snapshot/btrfs/btrfs_test.go b/snapshot/btrfs/btrfs_test.go index 732833713..53245ec15 100644 --- a/snapshot/btrfs/btrfs_test.go +++ b/snapshot/btrfs/btrfs_test.go @@ -222,45 +222,45 @@ func TestGetBtrfsDevice(t *testing.T) { expectedDevice string expectedError string root string - mounts []*mountinfo.Info + mounts []mountinfo.Info }{ { expectedDevice: "/dev/loop0", root: "/var/lib/containerd/snapshot/btrfs", - mounts: []*mountinfo.Info{ - {Root: "/", Mountpoint: "/", Fstype: "ext4", Source: "/dev/sda1"}, - {Root: "/", Mountpoint: "/var/lib/containerd/snapshot/btrfs", Fstype: "btrfs", Source: "/dev/loop0"}, + mounts: []mountinfo.Info{ + {Root: "/", Mountpoint: "/", FSType: "ext4", Source: "/dev/sda1"}, + {Root: "/", Mountpoint: "/var/lib/containerd/snapshot/btrfs", FSType: "btrfs", Source: "/dev/loop0"}, }, }, { expectedError: "/var/lib/containerd/snapshot/btrfs is not mounted as btrfs", root: "/var/lib/containerd/snapshot/btrfs", - mounts: []*mountinfo.Info{ - {Root: "/", Mountpoint: "/", Fstype: "ext4", Source: "/dev/sda1"}, + mounts: []mountinfo.Info{ + {Root: "/", Mountpoint: "/", FSType: "ext4", Source: "/dev/sda1"}, }, }, { expectedDevice: "/dev/sda1", root: "/var/lib/containerd/snapshot/btrfs", - mounts: []*mountinfo.Info{ - {Root: "/", Mountpoint: "/", Fstype: "btrfs", Source: "/dev/sda1"}, + mounts: []mountinfo.Info{ + {Root: "/", Mountpoint: "/", FSType: "btrfs", Source: "/dev/sda1"}, }, }, { expectedDevice: "/dev/sda2", root: "/var/lib/containerd/snapshot/btrfs", - mounts: []*mountinfo.Info{ - {Root: "/", Mountpoint: "/", Fstype: "btrfs", Source: "/dev/sda1"}, - {Root: "/", Mountpoint: "/var/lib/containerd/snapshot/btrfs", Fstype: "btrfs", Source: "/dev/sda2"}, + mounts: []mountinfo.Info{ + {Root: "/", Mountpoint: "/", FSType: "btrfs", Source: "/dev/sda1"}, + {Root: "/", Mountpoint: "/var/lib/containerd/snapshot/btrfs", FSType: "btrfs", Source: "/dev/sda2"}, }, }, { expectedDevice: "/dev/sda2", root: "/var/lib/containerd/snapshot/btrfs", - mounts: []*mountinfo.Info{ - {Root: "/", Mountpoint: "/var/lib/containerd/snapshot/btrfs", Fstype: "btrfs", Source: "/dev/sda2"}, - {Root: "/", Mountpoint: "/var/lib/foooooooooooooooooooo/baaaaaaaaaaaaaaaaaaaar", Fstype: "btrfs", Source: "/dev/sda3"}, // mountpoint length longer than /var/lib/containerd/snapshot/btrfs - {Root: "/", Mountpoint: "/", Fstype: "btrfs", Source: "/dev/sda1"}, + mounts: []mountinfo.Info{ + {Root: "/", Mountpoint: "/var/lib/containerd/snapshot/btrfs", FSType: "btrfs", Source: "/dev/sda2"}, + {Root: "/", Mountpoint: "/var/lib/foooooooooooooooooooo/baaaaaaaaaaaaaaaaaaaar", FSType: "btrfs", Source: "/dev/sda3"}, // mountpoint length longer than /var/lib/containerd/snapshot/btrfs + {Root: "/", Mountpoint: "/", FSType: "btrfs", Source: "/dev/sda1"}, }, }, }