mount: add mount.Lookup for ease of implementing snapshotters
`func Lookup(dir string) (Info, error)` returns the mount info that corresponds to the dir Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
This commit is contained in:
3
mount/lookup_test/dummy.go
Normal file
3
mount/lookup_test/dummy.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package lookuptest
|
||||
|
||||
// FIXME: without this dummy file, `make build` fails with "no buildable Go source files" error
|
||||
59
mount/lookup_test/lookup_linux_test.go
Normal file
59
mount/lookup_test/lookup_linux_test.go
Normal file
@@ -0,0 +1,59 @@
|
||||
// +build linux
|
||||
|
||||
// FIXME: we can't put this test to the mount package:
|
||||
// import cycle not allowed in test
|
||||
// package github.com/containerd/containerd/mount (test)
|
||||
// imports github.com/containerd/containerd/testutil
|
||||
// imports github.com/containerd/containerd/mount
|
||||
//
|
||||
// NOTE: we can't have this as lookup_test (compilation fails)
|
||||
package lookuptest
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/containerd/containerd/mount"
|
||||
"github.com/containerd/containerd/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func testLookup(t *testing.T, fsType string) {
|
||||
testutil.RequiresRoot(t)
|
||||
mnt, err := ioutil.TempDir("", "containerd-mountinfo-test-lookup")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(mnt)
|
||||
|
||||
deviceName, cleanupDevice := testutil.NewLoopback(t, 100<<20) // 100 MB
|
||||
if out, err := exec.Command("mkfs", "-t", fsType, deviceName).CombinedOutput(); err != nil {
|
||||
// not fatal
|
||||
t.Skipf("could not mkfs (%s) %s: %v (out: %q)", fsType, deviceName, err, string(out))
|
||||
}
|
||||
if out, err := exec.Command("mount", deviceName, mnt).CombinedOutput(); err != nil {
|
||||
// not fatal
|
||||
t.Skipf("could not mount %s: %v (out: %q)", deviceName, err, string(out))
|
||||
}
|
||||
defer func() {
|
||||
testutil.Unmount(t, mnt)
|
||||
cleanupDevice()
|
||||
}()
|
||||
assert.True(t, strings.HasPrefix(deviceName, "/dev/loop"))
|
||||
info, err := mount.Lookup(mnt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, fsType, info.FSType)
|
||||
}
|
||||
|
||||
func TestLookupWithExt4(t *testing.T) {
|
||||
testLookup(t, "ext4")
|
||||
}
|
||||
|
||||
func TestLookupWithXFS(t *testing.T) {
|
||||
testLookup(t, "xfs")
|
||||
}
|
||||
37
mount/lookup_unix.go
Normal file
37
mount/lookup_unix.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// +build !windows
|
||||
|
||||
package mount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Lookup returns the mount info corresponds to the path.
|
||||
func Lookup(dir string) (Info, error) {
|
||||
var dirStat syscall.Stat_t
|
||||
if err := syscall.Stat(dir, &dirStat); err != nil {
|
||||
return Info{}, errors.Wrapf(err, "failed to access %q", dir)
|
||||
}
|
||||
|
||||
mounts, err := Self()
|
||||
if err != nil {
|
||||
return Info{}, err
|
||||
}
|
||||
for _, m := range mounts {
|
||||
// Note that m.{Major, Minor} are generally unreliable for our purpose here
|
||||
// https://www.spinics.net/lists/linux-btrfs/msg58908.html
|
||||
var st syscall.Stat_t
|
||||
if err := syscall.Stat(m.Mountpoint, &st); err != nil {
|
||||
// may fail; ignore err
|
||||
continue
|
||||
}
|
||||
if st.Dev == dirStat.Dev {
|
||||
return m, nil
|
||||
}
|
||||
}
|
||||
|
||||
return Info{}, fmt.Errorf("failed to find the mount info for %q", dir)
|
||||
}
|
||||
13
mount/lookup_unsupported.go
Normal file
13
mount/lookup_unsupported.go
Normal file
@@ -0,0 +1,13 @@
|
||||
// +build windows
|
||||
|
||||
package mount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// Lookup returns the mount info corresponds to the path.
|
||||
func Lookup(dir string) (Info, error) {
|
||||
return Info{}, fmt.Errorf("mount.Lookup is not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
Reference in New Issue
Block a user