Browse code

Merge pull request #36091 from kolyshkin/mount

pkg/mount improvements

Vincent Demeester authored on 2018/04/21 18:03:54
Showing 15 changed files
... ...
@@ -74,18 +74,22 @@ func (daemon *Daemon) cleanupMounts() error {
74 74
 		return err
75 75
 	}
76 76
 
77
-	infos, err := mount.GetMounts()
77
+	info, err := mount.GetMounts(mount.SingleEntryFilter(daemon.root))
78 78
 	if err != nil {
79 79
 		return errors.Wrap(err, "error reading mount table for cleanup")
80 80
 	}
81 81
 
82
-	info := getMountInfo(infos, daemon.root)
82
+	if len(info) < 1 {
83
+		// no mount found, we're done here
84
+		return nil
85
+	}
86
+
83 87
 	// `info.Root` here is the root mountpoint of the passed in path (`daemon.root`).
84 88
 	// The ony cases that need to be cleaned up is when the daemon has performed a
85 89
 	//   `mount --bind /daemon/root /daemon/root && mount --make-shared /daemon/root`
86 90
 	// This is only done when the daemon is started up and `/daemon/root` is not
87 91
 	// already on a shared mountpoint.
88
-	if !shouldUnmountRoot(daemon.root, info) {
92
+	if !shouldUnmountRoot(daemon.root, info[0]) {
89 93
 		return nil
90 94
 	}
91 95
 
... ...
@@ -122,12 +126,6 @@ func getRealPath(path string) (string, error) {
122 122
 }
123 123
 
124 124
 func shouldUnmountRoot(root string, info *mount.Info) bool {
125
-	if info == nil {
126
-		return false
127
-	}
128
-	if info.Mountpoint != root {
129
-		return false
130
-	}
131 125
 	if !strings.HasSuffix(root, info.Root) {
132 126
 		return false
133 127
 	}
... ...
@@ -184,12 +184,6 @@ func TestShouldUnmountRoot(t *testing.T) {
184 184
 			expect: true,
185 185
 		},
186 186
 		{
187
-			desc:   "not a mountpoint",
188
-			root:   "/docker",
189
-			info:   nil,
190
-			expect: false,
191
-		},
192
-		{
193 187
 			desc:   "root is at in a submount from `/`",
194 188
 			root:   "/foo/docker",
195 189
 			info:   &mount.Info{Root: "/docker", Mountpoint: "/foo/docker"},
... ...
@@ -201,12 +195,6 @@ func TestShouldUnmountRoot(t *testing.T) {
201 201
 			info:   &mount.Info{Root: "/docker/volumes/1234657/_data", Mountpoint: "/docker"},
202 202
 			expect: false,
203 203
 		},
204
-		{
205
-			desc:   "root is mounted in from a parent mount namespace different root dir",
206
-			root:   "/foo/bar",
207
-			info:   &mount.Info{Root: "/docker/volumes/1234657/_data", Mountpoint: "/foo/bar"},
208
-			expect: false,
209
-		},
210 204
 	} {
211 205
 		t.Run(test.desc, func(t *testing.T) {
212 206
 			for _, options := range []struct {
... ...
@@ -147,7 +147,7 @@ func lookupZfsDataset(rootdir string) (string, error) {
147 147
 	}
148 148
 	wantedDev := stat.Dev
149 149
 
150
-	mounts, err := mount.GetMounts()
150
+	mounts, err := mount.GetMounts(nil)
151 151
 	if err != nil {
152 152
 		return "", err
153 153
 	}
... ...
@@ -380,15 +380,6 @@ func specMapping(s []idtools.IDMap) []specs.LinuxIDMapping {
380 380
 	return ids
381 381
 }
382 382
 
383
-func getMountInfo(mountinfo []*mount.Info, dir string) *mount.Info {
384
-	for _, m := range mountinfo {
385
-		if m.Mountpoint == dir {
386
-			return m
387
-		}
388
-	}
389
-	return nil
390
-}
391
-
392 383
 // Get the source mount point of directory passed in as argument. Also return
393 384
 // optional fields.
394 385
 func getSourceMount(source string) (string, string, error) {
... ...
@@ -398,29 +389,26 @@ func getSourceMount(source string) (string, string, error) {
398 398
 		return "", "", err
399 399
 	}
400 400
 
401
-	mountinfos, err := mount.GetMounts()
401
+	mi, err := mount.GetMounts(mount.ParentsFilter(sourcePath))
402 402
 	if err != nil {
403 403
 		return "", "", err
404 404
 	}
405
-
406
-	mountinfo := getMountInfo(mountinfos, sourcePath)
407
-	if mountinfo != nil {
408
-		return sourcePath, mountinfo.Optional, nil
405
+	if len(mi) < 1 {
406
+		return "", "", fmt.Errorf("Can't find mount point of %s", source)
409 407
 	}
410 408
 
411
-	path := sourcePath
412
-	for {
413
-		path = filepath.Dir(path)
414
-
415
-		mountinfo = getMountInfo(mountinfos, path)
416
-		if mountinfo != nil {
417
-			return path, mountinfo.Optional, nil
418
-		}
419
-
420
-		if path == "/" {
421
-			break
409
+	// find the longest mount point
410
+	var idx, maxlen int
411
+	for i := range mi {
412
+		if len(mi[i].Mountpoint) > maxlen {
413
+			maxlen = len(mi[i].Mountpoint)
414
+			idx = i
422 415
 		}
423 416
 	}
417
+	// and return it unless it's "/"
418
+	if mi[idx].Mountpoint != "/" {
419
+		return mi[idx].Mountpoint, mi[idx].Optional, nil
420
+	}
424 421
 
425 422
 	// If we are here, we did not find parent mount. Something is wrong.
426 423
 	return "", "", fmt.Errorf("Could not find source mount of %s", source)
... ...
@@ -260,7 +260,7 @@ func (s *DockerDaemonSuite) TestPluginVolumeRemoveOnRestart(c *check.C) {
260 260
 }
261 261
 
262 262
 func existsMountpointWithPrefix(mountpointPrefix string) (bool, error) {
263
-	mounts, err := mount.GetMounts()
263
+	mounts, err := mount.GetMounts(nil)
264 264
 	if err != nil {
265 265
 		return false, err
266 266
 	}
... ...
@@ -3,32 +3,64 @@ package mount // import "github.com/docker/docker/pkg/mount"
3 3
 import (
4 4
 	"sort"
5 5
 	"strings"
6
-
7 6
 	"syscall"
8 7
 
9 8
 	"github.com/sirupsen/logrus"
10 9
 )
11 10
 
12
-// GetMounts retrieves a list of mounts for the current running process.
13
-func GetMounts() ([]*Info, error) {
14
-	return parseMountTable()
11
+// FilterFunc is a type defining a callback function
12
+// to filter out unwanted entries. It takes a pointer
13
+// to an Info struct (not fully populated, currently
14
+// only Mountpoint is filled in), and returns two booleans:
15
+//  - skip: true if the entry should be skipped
16
+//  - stop: true if parsing should be stopped after the entry
17
+type FilterFunc func(*Info) (skip, stop bool)
18
+
19
+// PrefixFilter discards all entries whose mount points
20
+// do not start with a prefix specified
21
+func PrefixFilter(prefix string) FilterFunc {
22
+	return func(m *Info) (bool, bool) {
23
+		skip := !strings.HasPrefix(m.Mountpoint, prefix)
24
+		return skip, false
25
+	}
26
+}
27
+
28
+// SingleEntryFilter looks for a specific entry
29
+func SingleEntryFilter(mp string) FilterFunc {
30
+	return func(m *Info) (bool, bool) {
31
+		if m.Mountpoint == mp {
32
+			return false, true // don't skip, stop now
33
+		}
34
+		return true, false // skip, keep going
35
+	}
36
+}
37
+
38
+// ParentsFilter returns all entries whose mount points
39
+// can be parents of a path specified, discarding others.
40
+// For example, given `/var/lib/docker/something`, entries
41
+// like `/var/lib/docker`, `/var` and `/` are returned.
42
+func ParentsFilter(path string) FilterFunc {
43
+	return func(m *Info) (bool, bool) {
44
+		skip := !strings.HasPrefix(path, m.Mountpoint)
45
+		return skip, false
46
+	}
47
+}
48
+
49
+// GetMounts retrieves a list of mounts for the current running process,
50
+// with an optional filter applied (use nil for no filter).
51
+func GetMounts(f FilterFunc) ([]*Info, error) {
52
+	return parseMountTable(f)
15 53
 }
16 54
 
17 55
 // Mounted determines if a specified mountpoint has been mounted.
18 56
 // On Linux it looks at /proc/self/mountinfo.
19 57
 func Mounted(mountpoint string) (bool, error) {
20
-	entries, err := parseMountTable()
58
+	entries, err := GetMounts(SingleEntryFilter(mountpoint))
21 59
 	if err != nil {
22 60
 		return false, err
23 61
 	}
24 62
 
25
-	// Search the table for the mountpoint
26
-	for _, e := range entries {
27
-		if e.Mountpoint == mountpoint {
28
-			return true, nil
29
-		}
30
-	}
31
-	return false, nil
63
+	return len(entries) > 0, nil
32 64
 }
33 65
 
34 66
 // Mount will mount filesystem according to the specified configuration, on the
... ...
@@ -57,16 +89,18 @@ func ForceMount(device, target, mType, options string) error {
57 57
 // Unmount lazily unmounts a filesystem on supported platforms, otherwise
58 58
 // does a normal unmount.
59 59
 func Unmount(target string) error {
60
-	if mounted, err := Mounted(target); err != nil || !mounted {
61
-		return err
60
+	err := unmount(target, mntDetach)
61
+	if err == syscall.EINVAL {
62
+		// ignore "not mounted" error
63
+		err = nil
62 64
 	}
63
-	return unmount(target, mntDetach)
65
+	return err
64 66
 }
65 67
 
66 68
 // RecursiveUnmount unmounts the target and all mounts underneath, starting with
67 69
 // the deepsest mount first.
68 70
 func RecursiveUnmount(target string) error {
69
-	mounts, err := GetMounts()
71
+	mounts, err := parseMountTable(PrefixFilter(target))
70 72
 	if err != nil {
71 73
 		return err
72 74
 	}
... ...
@@ -77,9 +111,6 @@ func RecursiveUnmount(target string) error {
77 77
 	})
78 78
 
79 79
 	for i, m := range mounts {
80
-		if !strings.HasPrefix(m.Mountpoint, target) {
81
-			continue
82
-		}
83 80
 		logrus.Debugf("Trying to unmount %s", m.Mountpoint)
84 81
 		err = unmount(m.Mountpoint, mntDetach)
85 82
 		if err != nil {
... ...
@@ -129,7 +129,7 @@ func TestMountReadonly(t *testing.T) {
129 129
 }
130 130
 
131 131
 func TestGetMounts(t *testing.T) {
132
-	mounts, err := GetMounts()
132
+	mounts, err := GetMounts(nil)
133 133
 	if err != nil {
134 134
 		t.Fatal(err)
135 135
 	}
... ...
@@ -121,7 +121,7 @@ func ensureUnmount(t *testing.T, mnt string) {
121 121
 
122 122
 // validateMount checks that mnt has the given options
123 123
 func validateMount(t *testing.T, mnt string, opts, optional, vfs string) {
124
-	info, err := GetMounts()
124
+	info, err := GetMounts(nil)
125 125
 	if err != nil {
126 126
 		t.Fatal(err)
127 127
 	}
... ...
@@ -15,7 +15,7 @@ import (
15 15
 
16 16
 // Parse /proc/self/mountinfo because comparing Dev and ino does not work from
17 17
 // bind mounts.
18
-func parseMountTable() ([]*Info, error) {
18
+func parseMountTable(filter FilterFunc) ([]*Info, error) {
19 19
 	var rawEntries *C.struct_statfs
20 20
 
21 21
 	count := int(C.getmntinfo(&rawEntries, C.MNT_WAIT))
... ...
@@ -32,10 +32,24 @@ func parseMountTable() ([]*Info, error) {
32 32
 	var out []*Info
33 33
 	for _, entry := range entries {
34 34
 		var mountinfo Info
35
+		var skip, stop bool
35 36
 		mountinfo.Mountpoint = C.GoString(&entry.f_mntonname[0])
37
+
38
+		if filter != nil {
39
+			// filter out entries we're not interested in
40
+			skip, stop = filter(p)
41
+			if skip {
42
+				continue
43
+			}
44
+		}
45
+
36 46
 		mountinfo.Source = C.GoString(&entry.f_mntfromname[0])
37 47
 		mountinfo.Fstype = C.GoString(&entry.f_fstypename[0])
48
+
38 49
 		out = append(out, &mountinfo)
50
+		if stop {
51
+			break
52
+		}
39 53
 	}
40 54
 	return out, nil
41 55
 }
... ...
@@ -5,80 +5,119 @@ import (
5 5
 	"fmt"
6 6
 	"io"
7 7
 	"os"
8
+	"strconv"
8 9
 	"strings"
9 10
 )
10 11
 
11
-const (
12
-	/* 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
13
-	   (1)(2)(3)   (4)   (5)      (6)      (7)   (8) (9)   (10)         (11)
12
+func parseInfoFile(r io.Reader, filter FilterFunc) ([]*Info, error) {
13
+	s := bufio.NewScanner(r)
14
+	out := []*Info{}
15
+	for s.Scan() {
16
+		if err := s.Err(); err != nil {
17
+			return nil, err
18
+		}
19
+		/*
20
+		   36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
21
+		   (1)(2)(3)   (4)   (5)      (6)      (7)   (8) (9)   (10)         (11)
14 22
 
15
-	   (1) mount ID:  unique identifier of the mount (may be reused after umount)
16
-	   (2) parent ID:  ID of parent (or of self for the top of the mount tree)
17
-	   (3) major:minor:  value of st_dev for files on filesystem
18
-	   (4) root:  root of the mount within the filesystem
19
-	   (5) mount point:  mount point relative to the process's root
20
-	   (6) mount options:  per mount options
21
-	   (7) optional fields:  zero or more fields of the form "tag[:value]"
22
-	   (8) separator:  marks the end of the optional fields
23
-	   (9) filesystem type:  name of filesystem of the form "type[.subtype]"
24
-	   (10) mount source:  filesystem specific information or "none"
25
-	   (11) super options:  per super block options*/
26
-	mountinfoFormat = "%d %d %d:%d %s %s %s %s"
27
-)
23
+		   (1) mount ID:  unique identifier of the mount (may be reused after umount)
24
+		   (2) parent ID:  ID of parent (or of self for the top of the mount tree)
25
+		   (3) major:minor:  value of st_dev for files on filesystem
26
+		   (4) root:  root of the mount within the filesystem
27
+		   (5) mount point:  mount point relative to the process's root
28
+		   (6) mount options:  per mount options
29
+		   (7) optional fields:  zero or more fields of the form "tag[:value]"
30
+		   (8) separator:  marks the end of the optional fields
31
+		   (9) filesystem type:  name of filesystem of the form "type[.subtype]"
32
+		   (10) mount source:  filesystem specific information or "none"
33
+		   (11) super options:  per super block options
34
+		*/
28 35
 
29
-// Parse /proc/self/mountinfo because comparing Dev and ino does not work from
30
-// bind mounts
31
-func parseMountTable() ([]*Info, error) {
32
-	f, err := os.Open("/proc/self/mountinfo")
33
-	if err != nil {
34
-		return nil, err
35
-	}
36
-	defer f.Close()
36
+		text := s.Text()
37
+		fields := strings.Split(text, " ")
38
+		numFields := len(fields)
39
+		if numFields < 10 {
40
+			// should be at least 10 fields
41
+			return nil, fmt.Errorf("Parsing '%s' failed: not enough fields (%d)", text, numFields)
42
+		}
37 43
 
38
-	return parseInfoFile(f)
39
-}
44
+		p := &Info{}
45
+		// ignore any numbers parsing errors, as there should not be any
46
+		p.ID, _ = strconv.Atoi(fields[0])
47
+		p.Parent, _ = strconv.Atoi(fields[1])
48
+		mm := strings.Split(fields[2], ":")
49
+		if len(mm) != 2 {
50
+			return nil, fmt.Errorf("Parsing '%s' failed: unexpected minor:major pair %s", text, mm)
51
+		}
52
+		p.Major, _ = strconv.Atoi(mm[0])
53
+		p.Minor, _ = strconv.Atoi(mm[1])
40 54
 
41
-func parseInfoFile(r io.Reader) ([]*Info, error) {
42
-	var (
43
-		s   = bufio.NewScanner(r)
44
-		out = []*Info{}
45
-	)
55
+		p.Root = fields[3]
56
+		p.Mountpoint = fields[4]
57
+		p.Opts = fields[5]
46 58
 
47
-	for s.Scan() {
48
-		if err := s.Err(); err != nil {
49
-			return nil, err
59
+		var skip, stop bool
60
+		if filter != nil {
61
+			// filter out entries we're not interested in
62
+			skip, stop = filter(p)
63
+			if skip {
64
+				continue
65
+			}
50 66
 		}
51 67
 
52
-		var (
53
-			p              = &Info{}
54
-			text           = s.Text()
55
-			optionalFields string
56
-		)
57
-
58
-		if _, err := fmt.Sscanf(text, mountinfoFormat,
59
-			&p.ID, &p.Parent, &p.Major, &p.Minor,
60
-			&p.Root, &p.Mountpoint, &p.Opts, &optionalFields); err != nil {
61
-			return nil, fmt.Errorf("Scanning '%s' failed: %s", text, err)
68
+		// one or more optional fields, when a separator (-)
69
+		i := 6
70
+		for ; i < numFields && fields[i] != "-"; i++ {
71
+			switch i {
72
+			case 6:
73
+				p.Optional = fields[6]
74
+			default:
75
+				/* NOTE there might be more optional fields before the such as
76
+				   fields[7]...fields[N] (where N < sepIndex), although
77
+				   as of Linux kernel 4.15 the only known ones are
78
+				   mount propagation flags in fields[6]. The correct
79
+				   behavior is to ignore any unknown optional fields.
80
+				*/
81
+				break
82
+			}
62 83
 		}
63
-		// Safe as mountinfo encodes mountpoints with spaces as \040.
64
-		index := strings.Index(text, " - ")
65
-		postSeparatorFields := strings.Fields(text[index+3:])
66
-		if len(postSeparatorFields) < 3 {
67
-			return nil, fmt.Errorf("Error found less than 3 fields post '-' in %q", text)
84
+		if i == numFields {
85
+			return nil, fmt.Errorf("Parsing '%s' failed: missing separator ('-')", text)
68 86
 		}
69 87
 
70
-		if optionalFields != "-" {
71
-			p.Optional = optionalFields
88
+		// There should be 3 fields after the separator...
89
+		if i+4 > numFields {
90
+			return nil, fmt.Errorf("Parsing '%s' failed: not enough fields after a separator", text)
72 91
 		}
92
+		// ... but in Linux <= 3.9 mounting a cifs with spaces in a share name
93
+		// (like "//serv/My Documents") _may_ end up having a space in the last field
94
+		// of mountinfo (like "unc=//serv/My Documents"). Since kernel 3.10-rc1, cifs
95
+		// option unc= is ignored,  so a space should not appear. In here we ignore
96
+		// those "extra" fields caused by extra spaces.
97
+		p.Fstype = fields[i+1]
98
+		p.Source = fields[i+2]
99
+		p.VfsOpts = fields[i+3]
73 100
 
74
-		p.Fstype = postSeparatorFields[0]
75
-		p.Source = postSeparatorFields[1]
76
-		p.VfsOpts = strings.Join(postSeparatorFields[2:], " ")
77 101
 		out = append(out, p)
102
+		if stop {
103
+			break
104
+		}
78 105
 	}
79 106
 	return out, nil
80 107
 }
81 108
 
109
+// Parse /proc/self/mountinfo because comparing Dev and ino does not work from
110
+// bind mounts
111
+func parseMountTable(filter FilterFunc) ([]*Info, error) {
112
+	f, err := os.Open("/proc/self/mountinfo")
113
+	if err != nil {
114
+		return nil, err
115
+	}
116
+	defer f.Close()
117
+
118
+	return parseInfoFile(f, filter)
119
+}
120
+
82 121
 // PidMountInfo collects the mounts for a specific process ID. If the process
83 122
 // ID is unknown, it is better to use `GetMounts` which will inspect
84 123
 // "/proc/self/mountinfo" instead.
... ...
@@ -89,5 +128,5 @@ func PidMountInfo(pid int) ([]*Info, error) {
89 89
 	}
90 90
 	defer f.Close()
91 91
 
92
-	return parseInfoFile(f)
92
+	return parseInfoFile(f, nil)
93 93
 }
... ...
@@ -5,67 +5,69 @@ package mount // import "github.com/docker/docker/pkg/mount"
5 5
 import (
6 6
 	"bytes"
7 7
 	"testing"
8
+
9
+	"github.com/gotestyourself/gotestyourself/assert"
8 10
 )
9 11
 
10 12
 const (
11 13
 	fedoraMountinfo = `15 35 0:3 / /proc rw,nosuid,nodev,noexec,relatime shared:5 - proc proc rw
12
-    16 35 0:14 / /sys rw,nosuid,nodev,noexec,relatime shared:6 - sysfs sysfs rw,seclabel
13
-    17 35 0:5 / /dev rw,nosuid shared:2 - devtmpfs devtmpfs rw,seclabel,size=8056484k,nr_inodes=2014121,mode=755
14
-    18 16 0:15 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:7 - securityfs securityfs rw
15
-    19 16 0:13 / /sys/fs/selinux rw,relatime shared:8 - selinuxfs selinuxfs rw
16
-    20 17 0:16 / /dev/shm rw,nosuid,nodev shared:3 - tmpfs tmpfs rw,seclabel
17
-    21 17 0:10 / /dev/pts rw,nosuid,noexec,relatime shared:4 - devpts devpts rw,seclabel,gid=5,mode=620,ptmxmode=000
18
-    22 35 0:17 / /run rw,nosuid,nodev shared:21 - tmpfs tmpfs rw,seclabel,mode=755
19
-    23 16 0:18 / /sys/fs/cgroup rw,nosuid,nodev,noexec shared:9 - tmpfs tmpfs rw,seclabel,mode=755
20
-    24 23 0:19 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd
21
-    25 16 0:20 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:20 - pstore pstore rw
22
-    26 23 0:21 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,cpuset,clone_children
23
-    27 23 0:22 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:12 - cgroup cgroup rw,cpuacct,cpu,clone_children
24
-    28 23 0:23 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:13 - cgroup cgroup rw,memory,clone_children
25
-    29 23 0:24 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,devices,clone_children
26
-    30 23 0:25 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,freezer,clone_children
27
-    31 23 0:26 / /sys/fs/cgroup/net_cls rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,net_cls,clone_children
28
-    32 23 0:27 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,blkio,clone_children
29
-    33 23 0:28 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,perf_event,clone_children
30
-    34 23 0:29 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,hugetlb,clone_children
31
-    35 1 253:2 / / rw,relatime shared:1 - ext4 /dev/mapper/ssd-root--f20 rw,seclabel,data=ordered
32
-    36 15 0:30 / /proc/sys/fs/binfmt_misc rw,relatime shared:22 - autofs systemd-1 rw,fd=38,pgrp=1,timeout=300,minproto=5,maxproto=5,direct
33
-    37 17 0:12 / /dev/mqueue rw,relatime shared:23 - mqueue mqueue rw,seclabel
34
-    38 35 0:31 / /tmp rw shared:24 - tmpfs tmpfs rw,seclabel
35
-    39 17 0:32 / /dev/hugepages rw,relatime shared:25 - hugetlbfs hugetlbfs rw,seclabel
36
-    40 16 0:7 / /sys/kernel/debug rw,relatime shared:26 - debugfs debugfs rw
37
-    41 16 0:33 / /sys/kernel/config rw,relatime shared:27 - configfs configfs rw
38
-    42 35 0:34 / /var/lib/nfs/rpc_pipefs rw,relatime shared:28 - rpc_pipefs sunrpc rw
39
-    43 15 0:35 / /proc/fs/nfsd rw,relatime shared:29 - nfsd sunrpc rw
40
-    45 35 8:17 / /boot rw,relatime shared:30 - ext4 /dev/sdb1 rw,seclabel,data=ordered
41
-    46 35 253:4 / /home rw,relatime shared:31 - ext4 /dev/mapper/ssd-home rw,seclabel,data=ordered
42
-    47 35 253:5 / /var/lib/libvirt/images rw,noatime,nodiratime shared:32 - ext4 /dev/mapper/ssd-virt rw,seclabel,discard,data=ordered
43
-    48 35 253:12 / /mnt/old rw,relatime shared:33 - ext4 /dev/mapper/HelpDeskRHEL6-FedoraRoot rw,seclabel,data=ordered
44
-    121 22 0:36 / /run/user/1000/gvfs rw,nosuid,nodev,relatime shared:104 - fuse.gvfsd-fuse gvfsd-fuse rw,user_id=1000,group_id=1000
45
-    124 16 0:37 / /sys/fs/fuse/connections rw,relatime shared:107 - fusectl fusectl rw
46
-    165 38 253:3 / /tmp/mnt rw,relatime shared:147 - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered
47
-    167 35 253:15 / /var/lib/docker/devicemapper/mnt/aae4076022f0e2b80a2afbf8fc6df450c52080191fcef7fb679a73e6f073e5c2 rw,relatime shared:149 - ext4 /dev/mapper/docker-253:2-425882-aae4076022f0e2b80a2afbf8fc6df450c52080191fcef7fb679a73e6f073e5c2 rw,seclabel,discard,stripe=16,data=ordered
48
-    171 35 253:16 / /var/lib/docker/devicemapper/mnt/c71be651f114db95180e472f7871b74fa597ee70a58ccc35cb87139ddea15373 rw,relatime shared:153 - ext4 /dev/mapper/docker-253:2-425882-c71be651f114db95180e472f7871b74fa597ee70a58ccc35cb87139ddea15373 rw,seclabel,discard,stripe=16,data=ordered
49
-    175 35 253:17 / /var/lib/docker/devicemapper/mnt/1bac6ab72862d2d5626560df6197cf12036b82e258c53d981fa29adce6f06c3c rw,relatime shared:157 - ext4 /dev/mapper/docker-253:2-425882-1bac6ab72862d2d5626560df6197cf12036b82e258c53d981fa29adce6f06c3c rw,seclabel,discard,stripe=16,data=ordered
50
-    179 35 253:18 / /var/lib/docker/devicemapper/mnt/d710a357d77158e80d5b2c55710ae07c94e76d34d21ee7bae65ce5418f739b09 rw,relatime shared:161 - ext4 /dev/mapper/docker-253:2-425882-d710a357d77158e80d5b2c55710ae07c94e76d34d21ee7bae65ce5418f739b09 rw,seclabel,discard,stripe=16,data=ordered
51
-    183 35 253:19 / /var/lib/docker/devicemapper/mnt/6479f52366114d5f518db6837254baab48fab39f2ac38d5099250e9a6ceae6c7 rw,relatime shared:165 - ext4 /dev/mapper/docker-253:2-425882-6479f52366114d5f518db6837254baab48fab39f2ac38d5099250e9a6ceae6c7 rw,seclabel,discard,stripe=16,data=ordered
52
-    187 35 253:20 / /var/lib/docker/devicemapper/mnt/8d9df91c4cca5aef49eeb2725292aab324646f723a7feab56be34c2ad08268e1 rw,relatime shared:169 - ext4 /dev/mapper/docker-253:2-425882-8d9df91c4cca5aef49eeb2725292aab324646f723a7feab56be34c2ad08268e1 rw,seclabel,discard,stripe=16,data=ordered
53
-    191 35 253:21 / /var/lib/docker/devicemapper/mnt/c8240b768603d32e920d365dc9d1dc2a6af46cd23e7ae819947f969e1b4ec661 rw,relatime shared:173 - ext4 /dev/mapper/docker-253:2-425882-c8240b768603d32e920d365dc9d1dc2a6af46cd23e7ae819947f969e1b4ec661 rw,seclabel,discard,stripe=16,data=ordered
54
-    195 35 253:22 / /var/lib/docker/devicemapper/mnt/2eb3a01278380bbf3ed12d86ac629eaa70a4351301ee307a5cabe7b5f3b1615f rw,relatime shared:177 - ext4 /dev/mapper/docker-253:2-425882-2eb3a01278380bbf3ed12d86ac629eaa70a4351301ee307a5cabe7b5f3b1615f rw,seclabel,discard,stripe=16,data=ordered
55
-    199 35 253:23 / /var/lib/docker/devicemapper/mnt/37a17fb7c9d9b80821235d5f2662879bd3483915f245f9b49cdaa0e38779b70b rw,relatime shared:181 - ext4 /dev/mapper/docker-253:2-425882-37a17fb7c9d9b80821235d5f2662879bd3483915f245f9b49cdaa0e38779b70b rw,seclabel,discard,stripe=16,data=ordered
56
-    203 35 253:24 / /var/lib/docker/devicemapper/mnt/aea459ae930bf1de913e2f29428fd80ee678a1e962d4080019d9f9774331ee2b rw,relatime shared:185 - ext4 /dev/mapper/docker-253:2-425882-aea459ae930bf1de913e2f29428fd80ee678a1e962d4080019d9f9774331ee2b rw,seclabel,discard,stripe=16,data=ordered
57
-    207 35 253:25 / /var/lib/docker/devicemapper/mnt/928ead0bc06c454bd9f269e8585aeae0a6bd697f46dc8754c2a91309bc810882 rw,relatime shared:189 - ext4 /dev/mapper/docker-253:2-425882-928ead0bc06c454bd9f269e8585aeae0a6bd697f46dc8754c2a91309bc810882 rw,seclabel,discard,stripe=16,data=ordered
58
-    211 35 253:26 / /var/lib/docker/devicemapper/mnt/0f284d18481d671644706e7a7244cbcf63d590d634cc882cb8721821929d0420 rw,relatime shared:193 - ext4 /dev/mapper/docker-253:2-425882-0f284d18481d671644706e7a7244cbcf63d590d634cc882cb8721821929d0420 rw,seclabel,discard,stripe=16,data=ordered
59
-    215 35 253:27 / /var/lib/docker/devicemapper/mnt/d9dd16722ab34c38db2733e23f69e8f4803ce59658250dd63e98adff95d04919 rw,relatime shared:197 - ext4 /dev/mapper/docker-253:2-425882-d9dd16722ab34c38db2733e23f69e8f4803ce59658250dd63e98adff95d04919 rw,seclabel,discard,stripe=16,data=ordered
60
-    219 35 253:28 / /var/lib/docker/devicemapper/mnt/bc4500479f18c2c08c21ad5282e5f826a016a386177d9874c2764751c031d634 rw,relatime shared:201 - ext4 /dev/mapper/docker-253:2-425882-bc4500479f18c2c08c21ad5282e5f826a016a386177d9874c2764751c031d634 rw,seclabel,discard,stripe=16,data=ordered
61
-    223 35 253:29 / /var/lib/docker/devicemapper/mnt/7770c8b24eb3d5cc159a065910076938910d307ab2f5d94e1dc3b24c06ee2c8a rw,relatime shared:205 - ext4 /dev/mapper/docker-253:2-425882-7770c8b24eb3d5cc159a065910076938910d307ab2f5d94e1dc3b24c06ee2c8a rw,seclabel,discard,stripe=16,data=ordered
62
-    227 35 253:30 / /var/lib/docker/devicemapper/mnt/c280cd3d0bf0aa36b478b292279671624cceafc1a67eaa920fa1082601297adf rw,relatime shared:209 - ext4 /dev/mapper/docker-253:2-425882-c280cd3d0bf0aa36b478b292279671624cceafc1a67eaa920fa1082601297adf rw,seclabel,discard,stripe=16,data=ordered
63
-    231 35 253:31 / /var/lib/docker/devicemapper/mnt/8b59a7d9340279f09fea67fd6ad89ddef711e9e7050eb647984f8b5ef006335f rw,relatime shared:213 - ext4 /dev/mapper/docker-253:2-425882-8b59a7d9340279f09fea67fd6ad89ddef711e9e7050eb647984f8b5ef006335f rw,seclabel,discard,stripe=16,data=ordered
64
-    235 35 253:32 / /var/lib/docker/devicemapper/mnt/1a28059f29eda821578b1bb27a60cc71f76f846a551abefabce6efd0146dce9f rw,relatime shared:217 - ext4 /dev/mapper/docker-253:2-425882-1a28059f29eda821578b1bb27a60cc71f76f846a551abefabce6efd0146dce9f rw,seclabel,discard,stripe=16,data=ordered
65
-    239 35 253:33 / /var/lib/docker/devicemapper/mnt/e9aa60c60128cad1 rw,relatime shared:221 - ext4 /dev/mapper/docker-253:2-425882-e9aa60c60128cad1 rw,seclabel,discard,stripe=16,data=ordered
66
-    243 35 253:34 / /var/lib/docker/devicemapper/mnt/5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d-init rw,relatime shared:225 - ext4 /dev/mapper/docker-253:2-425882-5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d-init rw,seclabel,discard,stripe=16,data=ordered
67
-    247 35 253:35 / /var/lib/docker/devicemapper/mnt/5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d rw,relatime shared:229 - ext4 /dev/mapper/docker-253:2-425882-5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d rw,seclabel,discard,stripe=16,data=ordered
68
-    31 21 0:23 / /DATA/foo_bla_bla rw,relatime - cifs //foo/BLA\040BLA\040BLA/ rw,sec=ntlm,cache=loose,unc=\\foo\BLA BLA BLA,username=my_login,domain=mydomain.com,uid=12345678,forceuid,gid=12345678,forcegid,addr=10.1.30.10,file_mode=0755,dir_mode=0755,nounix,rsize=61440,wsize=65536,actimeo=1`
14
+16 35 0:14 / /sys rw,nosuid,nodev,noexec,relatime shared:6 - sysfs sysfs rw,seclabel
15
+17 35 0:5 / /dev rw,nosuid shared:2 - devtmpfs devtmpfs rw,seclabel,size=8056484k,nr_inodes=2014121,mode=755
16
+18 16 0:15 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:7 - securityfs securityfs rw
17
+19 16 0:13 / /sys/fs/selinux rw,relatime shared:8 - selinuxfs selinuxfs rw
18
+20 17 0:16 / /dev/shm rw,nosuid,nodev shared:3 - tmpfs tmpfs rw,seclabel
19
+21 17 0:10 / /dev/pts rw,nosuid,noexec,relatime shared:4 - devpts devpts rw,seclabel,gid=5,mode=620,ptmxmode=000
20
+22 35 0:17 / /run rw,nosuid,nodev shared:21 - tmpfs tmpfs rw,seclabel,mode=755
21
+23 16 0:18 / /sys/fs/cgroup rw,nosuid,nodev,noexec shared:9 - tmpfs tmpfs rw,seclabel,mode=755
22
+24 23 0:19 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd
23
+25 16 0:20 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:20 - pstore pstore rw
24
+26 23 0:21 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,cpuset,clone_children
25
+27 23 0:22 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:12 - cgroup cgroup rw,cpuacct,cpu,clone_children
26
+28 23 0:23 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:13 - cgroup cgroup rw,memory,clone_children
27
+29 23 0:24 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,devices,clone_children
28
+30 23 0:25 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,freezer,clone_children
29
+31 23 0:26 / /sys/fs/cgroup/net_cls rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,net_cls,clone_children
30
+32 23 0:27 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,blkio,clone_children
31
+33 23 0:28 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,perf_event,clone_children
32
+34 23 0:29 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,hugetlb,clone_children
33
+35 1 253:2 / / rw,relatime shared:1 - ext4 /dev/mapper/ssd-root--f20 rw,seclabel,data=ordered
34
+36 15 0:30 / /proc/sys/fs/binfmt_misc rw,relatime shared:22 - autofs systemd-1 rw,fd=38,pgrp=1,timeout=300,minproto=5,maxproto=5,direct
35
+37 17 0:12 / /dev/mqueue rw,relatime shared:23 - mqueue mqueue rw,seclabel
36
+38 35 0:31 / /tmp rw shared:24 - tmpfs tmpfs rw,seclabel
37
+39 17 0:32 / /dev/hugepages rw,relatime shared:25 - hugetlbfs hugetlbfs rw,seclabel
38
+40 16 0:7 / /sys/kernel/debug rw,relatime shared:26 - debugfs debugfs rw
39
+41 16 0:33 / /sys/kernel/config rw,relatime shared:27 - configfs configfs rw
40
+42 35 0:34 / /var/lib/nfs/rpc_pipefs rw,relatime shared:28 - rpc_pipefs sunrpc rw
41
+43 15 0:35 / /proc/fs/nfsd rw,relatime shared:29 - nfsd sunrpc rw
42
+45 35 8:17 / /boot rw,relatime shared:30 - ext4 /dev/sdb1 rw,seclabel,data=ordered
43
+46 35 253:4 / /home rw,relatime shared:31 - ext4 /dev/mapper/ssd-home rw,seclabel,data=ordered
44
+47 35 253:5 / /var/lib/libvirt/images rw,noatime,nodiratime shared:32 - ext4 /dev/mapper/ssd-virt rw,seclabel,discard,data=ordered
45
+48 35 253:12 / /mnt/old rw,relatime shared:33 - ext4 /dev/mapper/HelpDeskRHEL6-FedoraRoot rw,seclabel,data=ordered
46
+121 22 0:36 / /run/user/1000/gvfs rw,nosuid,nodev,relatime shared:104 - fuse.gvfsd-fuse gvfsd-fuse rw,user_id=1000,group_id=1000
47
+124 16 0:37 / /sys/fs/fuse/connections rw,relatime shared:107 - fusectl fusectl rw
48
+165 38 253:3 / /tmp/mnt rw,relatime shared:147 - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered
49
+167 35 253:15 / /var/lib/docker/devicemapper/mnt/aae4076022f0e2b80a2afbf8fc6df450c52080191fcef7fb679a73e6f073e5c2 rw,relatime shared:149 - ext4 /dev/mapper/docker-253:2-425882-aae4076022f0e2b80a2afbf8fc6df450c52080191fcef7fb679a73e6f073e5c2 rw,seclabel,discard,stripe=16,data=ordered
50
+171 35 253:16 / /var/lib/docker/devicemapper/mnt/c71be651f114db95180e472f7871b74fa597ee70a58ccc35cb87139ddea15373 rw,relatime shared:153 - ext4 /dev/mapper/docker-253:2-425882-c71be651f114db95180e472f7871b74fa597ee70a58ccc35cb87139ddea15373 rw,seclabel,discard,stripe=16,data=ordered
51
+175 35 253:17 / /var/lib/docker/devicemapper/mnt/1bac6ab72862d2d5626560df6197cf12036b82e258c53d981fa29adce6f06c3c rw,relatime shared:157 - ext4 /dev/mapper/docker-253:2-425882-1bac6ab72862d2d5626560df6197cf12036b82e258c53d981fa29adce6f06c3c rw,seclabel,discard,stripe=16,data=ordered
52
+179 35 253:18 / /var/lib/docker/devicemapper/mnt/d710a357d77158e80d5b2c55710ae07c94e76d34d21ee7bae65ce5418f739b09 rw,relatime shared:161 - ext4 /dev/mapper/docker-253:2-425882-d710a357d77158e80d5b2c55710ae07c94e76d34d21ee7bae65ce5418f739b09 rw,seclabel,discard,stripe=16,data=ordered
53
+183 35 253:19 / /var/lib/docker/devicemapper/mnt/6479f52366114d5f518db6837254baab48fab39f2ac38d5099250e9a6ceae6c7 rw,relatime shared:165 - ext4 /dev/mapper/docker-253:2-425882-6479f52366114d5f518db6837254baab48fab39f2ac38d5099250e9a6ceae6c7 rw,seclabel,discard,stripe=16,data=ordered
54
+187 35 253:20 / /var/lib/docker/devicemapper/mnt/8d9df91c4cca5aef49eeb2725292aab324646f723a7feab56be34c2ad08268e1 rw,relatime shared:169 - ext4 /dev/mapper/docker-253:2-425882-8d9df91c4cca5aef49eeb2725292aab324646f723a7feab56be34c2ad08268e1 rw,seclabel,discard,stripe=16,data=ordered
55
+191 35 253:21 / /var/lib/docker/devicemapper/mnt/c8240b768603d32e920d365dc9d1dc2a6af46cd23e7ae819947f969e1b4ec661 rw,relatime shared:173 - ext4 /dev/mapper/docker-253:2-425882-c8240b768603d32e920d365dc9d1dc2a6af46cd23e7ae819947f969e1b4ec661 rw,seclabel,discard,stripe=16,data=ordered
56
+195 35 253:22 / /var/lib/docker/devicemapper/mnt/2eb3a01278380bbf3ed12d86ac629eaa70a4351301ee307a5cabe7b5f3b1615f rw,relatime shared:177 - ext4 /dev/mapper/docker-253:2-425882-2eb3a01278380bbf3ed12d86ac629eaa70a4351301ee307a5cabe7b5f3b1615f rw,seclabel,discard,stripe=16,data=ordered
57
+199 35 253:23 / /var/lib/docker/devicemapper/mnt/37a17fb7c9d9b80821235d5f2662879bd3483915f245f9b49cdaa0e38779b70b rw,relatime shared:181 - ext4 /dev/mapper/docker-253:2-425882-37a17fb7c9d9b80821235d5f2662879bd3483915f245f9b49cdaa0e38779b70b rw,seclabel,discard,stripe=16,data=ordered
58
+203 35 253:24 / /var/lib/docker/devicemapper/mnt/aea459ae930bf1de913e2f29428fd80ee678a1e962d4080019d9f9774331ee2b rw,relatime shared:185 - ext4 /dev/mapper/docker-253:2-425882-aea459ae930bf1de913e2f29428fd80ee678a1e962d4080019d9f9774331ee2b rw,seclabel,discard,stripe=16,data=ordered
59
+207 35 253:25 / /var/lib/docker/devicemapper/mnt/928ead0bc06c454bd9f269e8585aeae0a6bd697f46dc8754c2a91309bc810882 rw,relatime shared:189 - ext4 /dev/mapper/docker-253:2-425882-928ead0bc06c454bd9f269e8585aeae0a6bd697f46dc8754c2a91309bc810882 rw,seclabel,discard,stripe=16,data=ordered
60
+211 35 253:26 / /var/lib/docker/devicemapper/mnt/0f284d18481d671644706e7a7244cbcf63d590d634cc882cb8721821929d0420 rw,relatime shared:193 - ext4 /dev/mapper/docker-253:2-425882-0f284d18481d671644706e7a7244cbcf63d590d634cc882cb8721821929d0420 rw,seclabel,discard,stripe=16,data=ordered
61
+215 35 253:27 / /var/lib/docker/devicemapper/mnt/d9dd16722ab34c38db2733e23f69e8f4803ce59658250dd63e98adff95d04919 rw,relatime shared:197 - ext4 /dev/mapper/docker-253:2-425882-d9dd16722ab34c38db2733e23f69e8f4803ce59658250dd63e98adff95d04919 rw,seclabel,discard,stripe=16,data=ordered
62
+219 35 253:28 / /var/lib/docker/devicemapper/mnt/bc4500479f18c2c08c21ad5282e5f826a016a386177d9874c2764751c031d634 rw,relatime shared:201 - ext4 /dev/mapper/docker-253:2-425882-bc4500479f18c2c08c21ad5282e5f826a016a386177d9874c2764751c031d634 rw,seclabel,discard,stripe=16,data=ordered
63
+223 35 253:29 / /var/lib/docker/devicemapper/mnt/7770c8b24eb3d5cc159a065910076938910d307ab2f5d94e1dc3b24c06ee2c8a rw,relatime shared:205 - ext4 /dev/mapper/docker-253:2-425882-7770c8b24eb3d5cc159a065910076938910d307ab2f5d94e1dc3b24c06ee2c8a rw,seclabel,discard,stripe=16,data=ordered
64
+227 35 253:30 / /var/lib/docker/devicemapper/mnt/c280cd3d0bf0aa36b478b292279671624cceafc1a67eaa920fa1082601297adf rw,relatime shared:209 - ext4 /dev/mapper/docker-253:2-425882-c280cd3d0bf0aa36b478b292279671624cceafc1a67eaa920fa1082601297adf rw,seclabel,discard,stripe=16,data=ordered
65
+231 35 253:31 / /var/lib/docker/devicemapper/mnt/8b59a7d9340279f09fea67fd6ad89ddef711e9e7050eb647984f8b5ef006335f rw,relatime shared:213 - ext4 /dev/mapper/docker-253:2-425882-8b59a7d9340279f09fea67fd6ad89ddef711e9e7050eb647984f8b5ef006335f rw,seclabel,discard,stripe=16,data=ordered
66
+235 35 253:32 / /var/lib/docker/devicemapper/mnt/1a28059f29eda821578b1bb27a60cc71f76f846a551abefabce6efd0146dce9f rw,relatime shared:217 - ext4 /dev/mapper/docker-253:2-425882-1a28059f29eda821578b1bb27a60cc71f76f846a551abefabce6efd0146dce9f rw,seclabel,discard,stripe=16,data=ordered
67
+239 35 253:33 / /var/lib/docker/devicemapper/mnt/e9aa60c60128cad1 rw,relatime shared:221 - ext4 /dev/mapper/docker-253:2-425882-e9aa60c60128cad1 rw,seclabel,discard,stripe=16,data=ordered
68
+243 35 253:34 / /var/lib/docker/devicemapper/mnt/5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d-init rw,relatime shared:225 - ext4 /dev/mapper/docker-253:2-425882-5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d-init rw,seclabel,discard,stripe=16,data=ordered
69
+247 35 253:35 / /var/lib/docker/devicemapper/mnt/5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d rw,relatime shared:229 - ext4 /dev/mapper/docker-253:2-425882-5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d rw,seclabel,discard,stripe=16,data=ordered
70
+31 21 0:23 / /DATA/foo_bla_bla rw,relatime - cifs //foo/BLA\040BLA\040BLA/ rw,sec=ntlm,cache=loose,unc=\\foo\BLA BLA BLA,username=my_login,domain=mydomain.com,uid=12345678,forceuid,gid=12345678,forcegid,addr=10.1.30.10,file_mode=0755,dir_mode=0755,nounix,rsize=61440,wsize=65536,actimeo=1`
69 71
 
70 72
 	ubuntuMountInfo = `15 20 0:14 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw
71 73
 16 20 0:3 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
... ...
@@ -424,7 +426,7 @@ const (
424 424
 
425 425
 func TestParseFedoraMountinfo(t *testing.T) {
426 426
 	r := bytes.NewBuffer([]byte(fedoraMountinfo))
427
-	_, err := parseInfoFile(r)
427
+	_, err := parseInfoFile(r, nil)
428 428
 	if err != nil {
429 429
 		t.Fatal(err)
430 430
 	}
... ...
@@ -432,7 +434,7 @@ func TestParseFedoraMountinfo(t *testing.T) {
432 432
 
433 433
 func TestParseUbuntuMountinfo(t *testing.T) {
434 434
 	r := bytes.NewBuffer([]byte(ubuntuMountInfo))
435
-	_, err := parseInfoFile(r)
435
+	_, err := parseInfoFile(r, nil)
436 436
 	if err != nil {
437 437
 		t.Fatal(err)
438 438
 	}
... ...
@@ -440,7 +442,7 @@ func TestParseUbuntuMountinfo(t *testing.T) {
440 440
 
441 441
 func TestParseGentooMountinfo(t *testing.T) {
442 442
 	r := bytes.NewBuffer([]byte(gentooMountinfo))
443
-	_, err := parseInfoFile(r)
443
+	_, err := parseInfoFile(r, nil)
444 444
 	if err != nil {
445 445
 		t.Fatal(err)
446 446
 	}
... ...
@@ -448,7 +450,7 @@ func TestParseGentooMountinfo(t *testing.T) {
448 448
 
449 449
 func TestParseFedoraMountinfoFields(t *testing.T) {
450 450
 	r := bytes.NewBuffer([]byte(fedoraMountinfo))
451
-	infos, err := parseInfoFile(r)
451
+	infos, err := parseInfoFile(r, nil)
452 452
 	if err != nil {
453 453
 		t.Fatal(err)
454 454
 	}
... ...
@@ -474,3 +476,33 @@ func TestParseFedoraMountinfoFields(t *testing.T) {
474 474
 		t.Fatalf("expected %#v, got %#v", mi, infos[0])
475 475
 	}
476 476
 }
477
+
478
+func TestParseMountinfoFilters(t *testing.T) {
479
+	r := bytes.NewReader([]byte(fedoraMountinfo))
480
+
481
+	infos, err := parseInfoFile(r, SingleEntryFilter("/sys/fs/cgroup"))
482
+	assert.NilError(t, err)
483
+	assert.Equal(t, 1, len(infos))
484
+
485
+	r.Reset([]byte(fedoraMountinfo))
486
+	infos, err = parseInfoFile(r, SingleEntryFilter("nonexistent"))
487
+	assert.NilError(t, err)
488
+	assert.Equal(t, 0, len(infos))
489
+
490
+	r.Reset([]byte(fedoraMountinfo))
491
+	infos, err = parseInfoFile(r, PrefixFilter("/sys"))
492
+	assert.NilError(t, err)
493
+	// there are 18 entries starting with /sys in fedoraMountinfo
494
+	assert.Equal(t, 18, len(infos))
495
+
496
+	r.Reset([]byte(fedoraMountinfo))
497
+	infos, err = parseInfoFile(r, PrefixFilter("nonexistent"))
498
+	assert.NilError(t, err)
499
+	assert.Equal(t, 0, len(infos))
500
+
501
+	r.Reset([]byte(fedoraMountinfo))
502
+	infos, err = parseInfoFile(r, ParentsFilter("/sys/fs/cgroup/cpu,cpuacct"))
503
+	assert.NilError(t, err)
504
+	// there should be 4 results returned: /sys/fs/cgroup/cpu,cpuacct /sys/fs/cgroup /sys /
505
+	assert.Equal(t, 4, len(infos))
506
+}
... ...
@@ -7,6 +7,6 @@ import (
7 7
 	"runtime"
8 8
 )
9 9
 
10
-func parseMountTable() ([]*Info, error) {
10
+func parseMountTable(f FilterFunc) ([]*Info, error) {
11 11
 	return nil, fmt.Errorf("mount.parseMountTable is not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
12 12
 }
... ...
@@ -1,6 +1,6 @@
1 1
 package mount // import "github.com/docker/docker/pkg/mount"
2 2
 
3
-func parseMountTable() ([]*Info, error) {
3
+func parseMountTable(f FilterFunc) ([]*Info, error) {
4 4
 	// Do NOT return an error!
5 5
 	return nil, nil
6 6
 }
... ...
@@ -19,7 +19,6 @@ import (
19 19
 	"github.com/docker/docker/pkg/mount"
20 20
 	"github.com/docker/docker/volume"
21 21
 	"github.com/pkg/errors"
22
-	"github.com/sirupsen/logrus"
23 22
 )
24 23
 
25 24
 // VolumeDataPathName is the name of the directory where the volume data is stored.
... ...
@@ -66,11 +65,6 @@ func New(scope string, rootIDs idtools.IDPair) (*Root, error) {
66 66
 		return nil, err
67 67
 	}
68 68
 
69
-	mountInfos, err := mount.GetMounts()
70
-	if err != nil {
71
-		logrus.Debugf("error looking up mounts for local volume cleanup: %v", err)
72
-	}
73
-
74 69
 	for _, d := range dirs {
75 70
 		if !d.IsDir() {
76 71
 			continue
... ...
@@ -96,12 +90,7 @@ func New(scope string, rootIDs idtools.IDPair) (*Root, error) {
96 96
 			}
97 97
 
98 98
 			// unmount anything that may still be mounted (for example, from an unclean shutdown)
99
-			for _, info := range mountInfos {
100
-				if info.Mountpoint == v.path {
101
-					mount.Unmount(v.path)
102
-					break
103
-				}
104
-			}
99
+			mount.Unmount(v.path)
105 100
 		}
106 101
 	}
107 102
 
... ...
@@ -184,6 +184,10 @@ func TestCreateWithOpts(t *testing.T) {
184 184
 	if runtime.GOOS == "windows" {
185 185
 		t.Skip()
186 186
 	}
187
+	if os.Getuid() != 0 {
188
+		t.Skip("root required")
189
+	}
190
+
187 191
 	rootDir, err := ioutil.TempDir("", "local-volume-test")
188 192
 	if err != nil {
189 193
 		t.Fatal(err)
... ...
@@ -215,33 +219,27 @@ func TestCreateWithOpts(t *testing.T) {
215 215
 		}
216 216
 	}()
217 217
 
218
-	mountInfos, err := mount.GetMounts()
218
+	mountInfos, err := mount.GetMounts(mount.SingleEntryFilter(dir))
219 219
 	if err != nil {
220 220
 		t.Fatal(err)
221 221
 	}
222
-
223
-	var found bool
224
-	for _, info := range mountInfos {
225
-		if info.Mountpoint == dir {
226
-			found = true
227
-			if info.Fstype != "tmpfs" {
228
-				t.Fatalf("expected tmpfs mount, got %q", info.Fstype)
229
-			}
230
-			if info.Source != "tmpfs" {
231
-				t.Fatalf("expected tmpfs mount, got %q", info.Source)
232
-			}
233
-			if !strings.Contains(info.VfsOpts, "uid=1000") {
234
-				t.Fatalf("expected mount info to have uid=1000: %q", info.VfsOpts)
235
-			}
236
-			if !strings.Contains(info.VfsOpts, "size=1024k") {
237
-				t.Fatalf("expected mount info to have size=1024k: %q", info.VfsOpts)
238
-			}
239
-			break
240
-		}
222
+	if len(mountInfos) != 1 {
223
+		t.Fatalf("expected 1 mount, found %d: %+v", len(mountInfos), mountInfos)
241 224
 	}
242 225
 
243
-	if !found {
244
-		t.Fatal("mount not found")
226
+	info := mountInfos[0]
227
+	t.Logf("%+v", info)
228
+	if info.Fstype != "tmpfs" {
229
+		t.Fatalf("expected tmpfs mount, got %q", info.Fstype)
230
+	}
231
+	if info.Source != "tmpfs" {
232
+		t.Fatalf("expected tmpfs mount, got %q", info.Source)
233
+	}
234
+	if !strings.Contains(info.VfsOpts, "uid=1000") {
235
+		t.Fatalf("expected mount info to have uid=1000: %q", info.VfsOpts)
236
+	}
237
+	if !strings.Contains(info.VfsOpts, "size=1024k") {
238
+		t.Fatalf("expected mount info to have size=1024k: %q", info.VfsOpts)
245 239
 	}
246 240
 
247 241
 	if v.active.count != 1 {