From d0779a6145d5bd8b2245f751d27a7bfaeedc01ca Mon Sep 17 00:00:00 2001 From: Lantao Liu Date: Thu, 1 Feb 2018 02:28:26 +0000 Subject: [PATCH] Simplify mount.Lookup. Signed-off-by: Lantao Liu --- mount/lookup_test/lookup_linux_test.go | 60 +++++++++++++++++++++----- mount/lookup_unix.go | 19 +++----- 2 files changed, 54 insertions(+), 25 deletions(-) diff --git a/mount/lookup_test/lookup_linux_test.go b/mount/lookup_test/lookup_linux_test.go index 852053369..2c9070428 100644 --- a/mount/lookup_test/lookup_linux_test.go +++ b/mount/lookup_test/lookup_linux_test.go @@ -10,6 +10,7 @@ package lookuptest import ( + "fmt" "io/ioutil" "os" "os/exec" @@ -20,18 +21,19 @@ import ( "github.com/containerd/containerd/mount" "github.com/containerd/containerd/testutil" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -func testLookup(t *testing.T, fsType string) { - checkLookup := func(mntPoint, dir string) { - info, err := mount.Lookup(dir) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, fsType, info.FSType) - assert.Equal(t, mntPoint, info.Mountpoint) +func checkLookup(t *testing.T, fsType, mntPoint, dir string) { + info, err := mount.Lookup(dir) + if err != nil { + t.Fatal(err) } + assert.Equal(t, fsType, info.FSType) + assert.Equal(t, mntPoint, info.Mountpoint) +} +func testLookup(t *testing.T, fsType string) { testutil.RequiresRoot(t) mnt, err := ioutil.TempDir("", "containerd-mountinfo-test-lookup") if err != nil { @@ -56,7 +58,7 @@ func testLookup(t *testing.T, fsType string) { cleanupDevice() }() assert.True(t, strings.HasPrefix(deviceName, "/dev/loop")) - checkLookup(mnt, mnt) + checkLookup(t, fsType, mnt, mnt) newMnt, err := ioutil.TempDir("", "containerd-mountinfo-test-newMnt") if err != nil { @@ -70,14 +72,14 @@ func testLookup(t *testing.T, fsType string) { defer func() { testutil.Unmount(t, newMnt) }() - checkLookup(newMnt, newMnt) + checkLookup(t, fsType, newMnt, newMnt) subDir := filepath.Join(newMnt, "subDir") err = os.MkdirAll(subDir, 0700) if err != nil { t.Fatal(err) } - checkLookup(newMnt, subDir) + checkLookup(t, fsType, newMnt, subDir) } func TestLookupWithExt4(t *testing.T) { @@ -87,3 +89,39 @@ func TestLookupWithExt4(t *testing.T) { func TestLookupWithXFS(t *testing.T) { testLookup(t, "xfs") } + +func TestLookupWithOverlay(t *testing.T) { + lower, err := ioutil.TempDir("", "containerd-mountinfo-test-lower") + require.NoError(t, err) + defer os.RemoveAll(lower) + + upper, err := ioutil.TempDir("", "containerd-mountinfo-test-upper") + require.NoError(t, err) + defer os.RemoveAll(upper) + + work, err := ioutil.TempDir("", "containerd-mountinfo-test-work") + require.NoError(t, err) + defer os.RemoveAll(work) + + overlay, err := ioutil.TempDir("", "containerd-mountinfo-test-overlay") + require.NoError(t, err) + defer os.RemoveAll(overlay) + + if out, err := exec.Command("mount", "-t", "overlay", "overlay", "-o", fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", + lower, upper, work), overlay).CombinedOutput(); err != nil { + // not fatal + t.Skipf("could not mount overlay: %v (out: %q)", err, string(out)) + } + defer testutil.Unmount(t, overlay) + + testdir := filepath.Join(overlay, "testdir") + err = os.Mkdir(testdir, 0777) + require.NoError(t, err) + + testfile := filepath.Join(overlay, "testfile") + _, err = os.Create(testfile) + require.NoError(t, err) + + checkLookup(t, "overlay", overlay, testdir) + checkLookup(t, "overlay", overlay, testfile) +} diff --git a/mount/lookup_unix.go b/mount/lookup_unix.go index df9625a96..6e4fd0d24 100644 --- a/mount/lookup_unix.go +++ b/mount/lookup_unix.go @@ -3,22 +3,16 @@ package mount import ( - "fmt" "path/filepath" "sort" "strings" - "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 dir = filepath.Clean(dir) - if err := syscall.Stat(dir, &dirStat); err != nil { - return Info{}, errors.Wrapf(err, "failed to access %q", dir) - } mounts, err := Self() if err != nil { @@ -26,21 +20,18 @@ func Lookup(dir string) (Info, error) { } // Sort descending order by Info.Mountpoint - sort.Slice(mounts, func(i, j int) bool { + sort.SliceStable(mounts, func(i, j int) bool { return mounts[j].Mountpoint < mounts[i].Mountpoint }) 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 && strings.HasPrefix(dir, m.Mountpoint) { + // Note that device number is not checked here, because for overlayfs files + // may have different device number with the mountpoint. + if strings.HasPrefix(dir, m.Mountpoint) { return m, nil } } - return Info{}, fmt.Errorf("failed to find the mount info for %q", dir) + return Info{}, errors.Errorf("failed to find the mount info for %q", dir) }