Browse code

daemon/graphdriver: simplify Checker, remove NewFsChecker, NewDefaultChecker

The Checker interface was introduced in 1ba05cdb6ade7e3abd4c4c3221b5e27645460111
as an optimization to allow passing a simplified check for situations that
don't require mountinfo.Mounted to be executed (as that may result in parsing
`/proc/self/mountinfo`).

The Checker was defined as an interface with a single `IsMounted` method,
possibly with the intent to allow for additional kind of checks to be added.
No new additions were made since its inception 9 Years ago, and if a need would
arrive, could probably be implemented as part of the check.

This patch simplifies the definition to a function, removing the need to
implement a wrapper struct just to satisfy the interface. The `Checker`
type definition is somewhat redundant, but is kept to have a place to
provide GoDoc.

The `NewFsChecker` and `NewDefaultChecker` utilities are removed as part
of this change, favoring a local definition for storage-drivers that
used them.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2024/06/30 20:13:32
Showing 11 changed files
... ...
@@ -9,16 +9,20 @@ type minfo struct {
9 9
 
10 10
 // RefCounter is a generic counter for use by graphdriver Get/Put calls
11 11
 type RefCounter struct {
12
-	counts  map[string]*minfo
13
-	mu      sync.Mutex
14
-	checker Checker
12
+	counts    map[string]*minfo
13
+	mu        sync.Mutex
14
+	isMounted Checker
15 15
 }
16 16
 
17
-// NewRefCounter returns a new RefCounter
17
+// Checker checks whether the provided path is mounted.
18
+type Checker func(path string) bool
19
+
20
+// NewRefCounter returns a new RefCounter. It accepts a [Checker] to
21
+// determine whether a path is mounted.
18 22
 func NewRefCounter(c Checker) *RefCounter {
19 23
 	return &RefCounter{
20
-		checker: c,
21
-		counts:  make(map[string]*minfo),
24
+		isMounted: c,
25
+		counts:    make(map[string]*minfo),
22 26
 	}
23 27
 }
24 28
 
... ...
@@ -48,7 +52,7 @@ func (c *RefCounter) incdec(path string, infoOp func(minfo *minfo)) int {
48 48
 	// count if it is mounted as it is in use.
49 49
 	if !m.check {
50 50
 		m.check = true
51
-		if c.checker.IsMounted(path) {
51
+		if c.isMounted(path) {
52 52
 			m.count++
53 53
 		}
54 54
 	}
... ...
@@ -128,12 +128,6 @@ type FileGetCloser interface {
128 128
 	Close() error
129 129
 }
130 130
 
131
-// Checker makes checks on specified filesystems.
132
-type Checker interface {
133
-	// IsMounted returns true if the provided path is mounted for the specific checker
134
-	IsMounted(path string) bool
135
-}
136
-
137 131
 func init() {
138 132
 	drivers = make(map[string]InitFunc)
139 133
 }
... ...
@@ -1,38 +1,4 @@
1 1
 package graphdriver // import "github.com/docker/docker/daemon/graphdriver"
2 2
 
3
-import (
4
-	"github.com/docker/docker/daemon/internal/fstype"
5
-	"github.com/moby/sys/mountinfo"
6
-)
7
-
8 3
 // List of drivers that should be used in an order
9 4
 var priority = "overlay2,fuse-overlayfs,btrfs,zfs,vfs"
10
-
11
-// NewFsChecker returns a checker configured for the provided FsMagic
12
-func NewFsChecker(t fstype.FsMagic) Checker {
13
-	return &fsChecker{
14
-		t: t,
15
-	}
16
-}
17
-
18
-type fsChecker struct {
19
-	t fstype.FsMagic
20
-}
21
-
22
-func (c *fsChecker) IsMounted(path string) bool {
23
-	fsType, _ := fstype.GetFSMagic(path)
24
-	return fsType == c.t
25
-}
26
-
27
-// NewDefaultChecker returns a check that parses /proc/mountinfo to check
28
-// if the specified path is mounted.
29
-func NewDefaultChecker() Checker {
30
-	return &defaultChecker{}
31
-}
32
-
33
-type defaultChecker struct{}
34
-
35
-func (c *defaultChecker) IsMounted(path string) bool {
36
-	m, _ := mountinfo.Mounted(path)
37
-	return m
38
-}
... ...
@@ -98,7 +98,7 @@ func Init(home string, options []string, idMap idtools.IdentityMapping) (graphdr
98 98
 	d := &Driver{
99 99
 		home:   home,
100 100
 		idMap:  idMap,
101
-		ctr:    graphdriver.NewRefCounter(graphdriver.NewFsChecker(fstype.FsMagicFUSE)),
101
+		ctr:    graphdriver.NewRefCounter(isMounted),
102 102
 		locker: locker.New(),
103 103
 	}
104 104
 
... ...
@@ -107,6 +107,12 @@ func Init(home string, options []string, idMap idtools.IdentityMapping) (graphdr
107 107
 	return d, nil
108 108
 }
109 109
 
110
+// isMounted checks whether the given path is a [fstype.FsMagicFUSE] mount.
111
+func isMounted(path string) bool {
112
+	fsType, _ := fstype.GetFSMagic(path)
113
+	return fsType == fstype.FsMagicFUSE
114
+}
115
+
110 116
 func (d *Driver) String() string {
111 117
 	return driverName
112 118
 }
... ...
@@ -179,7 +179,7 @@ func Init(home string, options []string, idMap idtools.IdentityMapping) (graphdr
179 179
 	d := &Driver{
180 180
 		home:          home,
181 181
 		idMap:         idMap,
182
-		ctr:           graphdriver.NewRefCounter(graphdriver.NewFsChecker(fstype.FsMagicOverlay)),
182
+		ctr:           graphdriver.NewRefCounter(isMounted),
183 183
 		supportsDType: supportsDType,
184 184
 		usingMetacopy: usingMetacopy,
185 185
 		locker:        locker.New(),
... ...
@@ -225,6 +225,12 @@ func Init(home string, options []string, idMap idtools.IdentityMapping) (graphdr
225 225
 	return d, nil
226 226
 }
227 227
 
228
+// isMounted checks whether the given path is a [fstype.FsMagicOverlay] mount.
229
+func isMounted(path string) bool {
230
+	fsType, _ := fstype.GetFSMagic(path)
231
+	return fsType == fstype.FsMagicOverlay
232
+}
233
+
228 234
 func parseOptions(options []string) (*overlayOptions, error) {
229 235
 	o := &overlayOptions{}
230 236
 	for _, option := range options {
... ...
@@ -72,12 +72,6 @@ func init() {
72 72
 	}
73 73
 }
74 74
 
75
-type checker struct{}
76
-
77
-func (c *checker) IsMounted(path string) bool {
78
-	return false
79
-}
80
-
81 75
 type storageOptions struct {
82 76
 	size uint64
83 77
 }
... ...
@@ -132,12 +126,18 @@ func InitFilter(home string, options []string, _ idtools.IdentityMapping) (graph
132 132
 			Flavour: filterDriver,
133 133
 		},
134 134
 		cache:              make(map[string]string),
135
-		ctr:                graphdriver.NewRefCounter(&checker{}),
135
+		ctr:                graphdriver.NewRefCounter(isMounted),
136 136
 		defaultStorageOpts: opts,
137 137
 	}
138 138
 	return d, nil
139 139
 }
140 140
 
141
+// isMounted checks whether the given path is mounted. It always returns
142
+// false for the WindowsFilter graphdriver.
143
+func isMounted(string) bool {
144
+	return false
145
+}
146
+
141 147
 // String returns the string representation of a driver. This should match
142 148
 // the name the graph driver has been registered with.
143 149
 func (d *Driver) String() string {
... ...
@@ -118,12 +118,19 @@ func Init(base string, opt []string, idMap idtools.IdentityMapping) (graphdriver
118 118
 		options:          options,
119 119
 		filesystemsCache: filesystemsCache,
120 120
 		idMap:            idMap,
121
-		ctr:              graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()),
121
+		ctr:              graphdriver.NewRefCounter(isMounted),
122 122
 		locker:           locker.New(),
123 123
 	}
124 124
 	return graphdriver.NewNaiveDiffDriver(d, idMap), nil
125 125
 }
126 126
 
127
+// isMounted parses /proc/mountinfo to check whether the specified path
128
+// is mounted.
129
+func isMounted(path string) bool {
130
+	m, _ := mountinfo.Mounted(path)
131
+	return m
132
+}
133
+
127 134
 func parseOptions(opt []string) (zfsOptions, error) {
128 135
 	var options zfsOptions
129 136
 	options.fsName = ""
... ...
@@ -32,7 +32,7 @@ func NewMounter(home string, snapshotter string, idMap idtools.IdentityMapping)
32 32
 			snapshotter: snapshotter,
33 33
 			idMap:       idMap,
34 34
 		},
35
-		rc:     graphdriver.NewRefCounter(checker()),
35
+		rc:     graphdriver.NewRefCounter(isMounted),
36 36
 		locker: locker.New(),
37 37
 	}
38 38
 }
39 39
deleted file mode 100644
... ...
@@ -1,17 +0,0 @@
1
-//go:build !windows
2
-
3
-package snapshotter
4
-
5
-import (
6
-	"github.com/containerd/containerd/mount"
7
-	"github.com/docker/docker/daemon/graphdriver"
8
-	"golang.org/x/sys/unix"
9
-)
10
-
11
-func checker() graphdriver.Checker {
12
-	return graphdriver.NewDefaultChecker()
13
-}
14
-
15
-func unmount(target string) error {
16
-	return mount.Unmount(target, unix.MNT_DETACH)
17
-}
18 1
new file mode 100644
... ...
@@ -0,0 +1,20 @@
0
+//go:build !windows
1
+
2
+package snapshotter
3
+
4
+import (
5
+	"github.com/containerd/containerd/mount"
6
+	"github.com/moby/sys/mountinfo"
7
+	"golang.org/x/sys/unix"
8
+)
9
+
10
+// isMounted parses /proc/mountinfo to check whether the specified path
11
+// is mounted.
12
+func isMounted(path string) bool {
13
+	m, _ := mountinfo.Mounted(path)
14
+	return m
15
+}
16
+
17
+func unmount(target string) error {
18
+	return mount.Unmount(target, unix.MNT_DETACH)
19
+}
... ...
@@ -2,15 +2,7 @@ package snapshotter
2 2
 
3 3
 import "github.com/containerd/containerd/mount"
4 4
 
5
-type winChecker struct{}
6
-
7
-func (c *winChecker) IsMounted(path string) bool {
8
-	return false
9
-}
10
-
11
-func checker() *winChecker {
12
-	return &winChecker{}
13
-}
5
+func isMounted(string) bool { return false }
14 6
 
15 7
 func unmount(target string) error {
16 8
 	return mount.Unmount(target, 0)