This changeset creates /dev/shm and /dev/mqueue mounts for each container under
/var/lib/containers/<id>/ and bind mounts them into the container. When --ipc:container<id/name>
is used, then the /dev/shm and /dev/mqueue of the ipc container are used instead of creating
new ones for the container.
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
Docker-DCO-1.1-Signed-off-by: Dan Walsh <dwalsh@redhat.com> (github: rhatdan)
(cherry picked from commit d88fe447df0e87b3a57f9d08b108b141dd72678c)
... | ... |
@@ -296,10 +296,17 @@ func (container *Container) Start() (err error) { |
296 | 296 |
return err |
297 | 297 |
} |
298 | 298 |
|
299 |
+ if !(container.hostConfig.IpcMode.IsContainer() || container.hostConfig.IpcMode.IsHost()) { |
|
300 |
+ if err := container.setupIpcDirs(); err != nil { |
|
301 |
+ return err |
|
302 |
+ } |
|
303 |
+ } |
|
304 |
+ |
|
299 | 305 |
mounts, err := container.setupMounts() |
300 | 306 |
if err != nil { |
301 | 307 |
return err |
302 | 308 |
} |
309 |
+ mounts = append(mounts, container.ipcMounts()...) |
|
303 | 310 |
|
304 | 311 |
container.command.Mounts = mounts |
305 | 312 |
return container.waitForStart() |
... | ... |
@@ -358,6 +365,10 @@ func (container *Container) isNetworkAllocated() bool { |
358 | 358 |
func (container *Container) cleanup() { |
359 | 359 |
container.releaseNetwork() |
360 | 360 |
|
361 |
+ if err := container.unmountIpcMounts(); err != nil { |
|
362 |
+ logrus.Errorf("%v: Failed to umount ipc filesystems: %v", container.ID, err) |
|
363 |
+ } |
|
364 |
+ |
|
361 | 365 |
if err := container.Unmount(); err != nil { |
362 | 366 |
logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err) |
363 | 367 |
} |
... | ... |
@@ -50,6 +50,8 @@ type Container struct { |
50 | 50 |
AppArmorProfile string |
51 | 51 |
HostnamePath string |
52 | 52 |
HostsPath string |
53 |
+ ShmPath string |
|
54 |
+ MqueuePath string |
|
53 | 55 |
MountPoints map[string]*mountPoint |
54 | 56 |
ResolvConfPath string |
55 | 57 |
|
... | ... |
@@ -189,6 +191,16 @@ func populateCommand(c *Container, env []string) error { |
189 | 189 |
} |
190 | 190 |
|
191 | 191 |
ipc := &execdriver.Ipc{} |
192 |
+ var err error |
|
193 |
+ c.ShmPath, err = c.shmPath() |
|
194 |
+ if err != nil { |
|
195 |
+ return err |
|
196 |
+ } |
|
197 |
+ |
|
198 |
+ c.MqueuePath, err = c.mqueuePath() |
|
199 |
+ if err != nil { |
|
200 |
+ return err |
|
201 |
+ } |
|
192 | 202 |
|
193 | 203 |
if c.hostConfig.IpcMode.IsContainer() { |
194 | 204 |
ic, err := c.getIpcContainer() |
... | ... |
@@ -196,8 +208,14 @@ func populateCommand(c *Container, env []string) error { |
196 | 196 |
return err |
197 | 197 |
} |
198 | 198 |
ipc.ContainerID = ic.ID |
199 |
+ c.ShmPath = ic.ShmPath |
|
200 |
+ c.MqueuePath = ic.MqueuePath |
|
199 | 201 |
} else { |
200 | 202 |
ipc.HostIpc = c.hostConfig.IpcMode.IsHost() |
203 |
+ if ipc.HostIpc { |
|
204 |
+ c.ShmPath = "/dev/shm" |
|
205 |
+ c.MqueuePath = "/dev/mqueue" |
|
206 |
+ } |
|
201 | 207 |
} |
202 | 208 |
|
203 | 209 |
pid := &execdriver.Pid{} |
... | ... |
@@ -1222,3 +1240,85 @@ func (container *Container) removeMountPoints(rm bool) error { |
1222 | 1222 |
} |
1223 | 1223 |
return nil |
1224 | 1224 |
} |
1225 |
+ |
|
1226 |
+func (container *Container) shmPath() (string, error) { |
|
1227 |
+ return container.GetRootResourcePath("shm") |
|
1228 |
+} |
|
1229 |
+func (container *Container) mqueuePath() (string, error) { |
|
1230 |
+ return container.GetRootResourcePath("mqueue") |
|
1231 |
+} |
|
1232 |
+ |
|
1233 |
+func (container *Container) setupIpcDirs() error { |
|
1234 |
+ shmPath, err := container.shmPath() |
|
1235 |
+ if err != nil { |
|
1236 |
+ return err |
|
1237 |
+ } |
|
1238 |
+ |
|
1239 |
+ if err := os.MkdirAll(shmPath, 0700); err != nil { |
|
1240 |
+ return err |
|
1241 |
+ } |
|
1242 |
+ |
|
1243 |
+ if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel("mode=1777,size=65536k", container.GetMountLabel())); err != nil { |
|
1244 |
+ return fmt.Errorf("mounting shm tmpfs: %s", err) |
|
1245 |
+ } |
|
1246 |
+ |
|
1247 |
+ mqueuePath, err := container.mqueuePath() |
|
1248 |
+ if err != nil { |
|
1249 |
+ return err |
|
1250 |
+ } |
|
1251 |
+ |
|
1252 |
+ if err := os.MkdirAll(mqueuePath, 0700); err != nil { |
|
1253 |
+ return err |
|
1254 |
+ } |
|
1255 |
+ |
|
1256 |
+ if err := syscall.Mount("mqueue", mqueuePath, "mqueue", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), ""); err != nil { |
|
1257 |
+ return fmt.Errorf("mounting mqueue mqueue : %s", err) |
|
1258 |
+ } |
|
1259 |
+ |
|
1260 |
+ return nil |
|
1261 |
+} |
|
1262 |
+ |
|
1263 |
+func (container *Container) unmountIpcMounts() error { |
|
1264 |
+ if container.hostConfig.IpcMode.IsContainer() || container.hostConfig.IpcMode.IsHost() { |
|
1265 |
+ return nil |
|
1266 |
+ } |
|
1267 |
+ |
|
1268 |
+ shmPath, err := container.shmPath() |
|
1269 |
+ if err != nil { |
|
1270 |
+ return fmt.Errorf("shm path does not exist %v", err) |
|
1271 |
+ } |
|
1272 |
+ |
|
1273 |
+ if err := syscall.Unmount(shmPath, syscall.MNT_DETACH); err != nil { |
|
1274 |
+ return fmt.Errorf("failed to umount %s filesystem %v", shmPath, err) |
|
1275 |
+ } |
|
1276 |
+ |
|
1277 |
+ mqueuePath, err := container.mqueuePath() |
|
1278 |
+ if err != nil { |
|
1279 |
+ return fmt.Errorf("mqueue path does not exist %v", err) |
|
1280 |
+ } |
|
1281 |
+ |
|
1282 |
+ if err := syscall.Unmount(mqueuePath, syscall.MNT_DETACH); err != nil { |
|
1283 |
+ return fmt.Errorf("failed to umount %s filesystem %v", mqueuePath, err) |
|
1284 |
+ } |
|
1285 |
+ |
|
1286 |
+ return nil |
|
1287 |
+} |
|
1288 |
+ |
|
1289 |
+func (container *Container) ipcMounts() []execdriver.Mount { |
|
1290 |
+ var mounts []execdriver.Mount |
|
1291 |
+ label.SetFileLabel(container.ShmPath, container.MountLabel) |
|
1292 |
+ mounts = append(mounts, execdriver.Mount{ |
|
1293 |
+ Source: container.ShmPath, |
|
1294 |
+ Destination: "/dev/shm", |
|
1295 |
+ Writable: true, |
|
1296 |
+ Private: true, |
|
1297 |
+ }) |
|
1298 |
+ label.SetFileLabel(container.MqueuePath, container.MountLabel) |
|
1299 |
+ mounts = append(mounts, execdriver.Mount{ |
|
1300 |
+ Source: container.MqueuePath, |
|
1301 |
+ Destination: "/dev/mqueue", |
|
1302 |
+ Writable: true, |
|
1303 |
+ Private: true, |
|
1304 |
+ }) |
|
1305 |
+ return mounts |
|
1306 |
+} |
... | ... |
@@ -163,3 +163,15 @@ func (container *Container) prepareMountPoints() error { |
163 | 163 |
func (container *Container) removeMountPoints(_ bool) error { |
164 | 164 |
return nil |
165 | 165 |
} |
166 |
+ |
|
167 |
+func (container *Container) setupIpcDirs() error { |
|
168 |
+ return nil |
|
169 |
+} |
|
170 |
+ |
|
171 |
+func (container *Container) unmountIpcMounts() error { |
|
172 |
+ return nil |
|
173 |
+} |
|
174 |
+ |
|
175 |
+func (container *Container) ipcMounts() []execdriver.Mount { |
|
176 |
+ return nil |
|
177 |
+} |
... | ... |
@@ -762,6 +762,10 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo |
762 | 762 |
return nil, err |
763 | 763 |
} |
764 | 764 |
|
765 |
+ if err := d.cleanupMounts(); err != nil { |
|
766 |
+ return nil, err |
|
767 |
+ } |
|
768 |
+ |
|
765 | 769 |
return d, nil |
766 | 770 |
} |
767 | 771 |
|
... | ... |
@@ -838,6 +842,10 @@ func (daemon *Daemon) Shutdown() error { |
838 | 838 |
} |
839 | 839 |
} |
840 | 840 |
|
841 |
+ if err := daemon.cleanupMounts(); err != nil { |
|
842 |
+ return err |
|
843 |
+ } |
|
844 |
+ |
|
841 | 845 |
return nil |
842 | 846 |
} |
843 | 847 |
|
844 | 848 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,44 @@ |
0 |
+package daemon |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "bufio" |
|
4 |
+ "os" |
|
5 |
+ "path/filepath" |
|
6 |
+ "strings" |
|
7 |
+ |
|
8 |
+ "github.com/Sirupsen/logrus" |
|
9 |
+ "github.com/docker/docker/pkg/mount" |
|
10 |
+) |
|
11 |
+ |
|
12 |
+// cleanupMounts umounts shm/mqueue mounts for old containers |
|
13 |
+func (daemon *Daemon) cleanupMounts() error { |
|
14 |
+ logrus.Debugf("Cleaning up old shm/mqueue mounts: start.") |
|
15 |
+ f, err := os.Open("/proc/self/mountinfo") |
|
16 |
+ if err != nil { |
|
17 |
+ return err |
|
18 |
+ } |
|
19 |
+ defer f.Close() |
|
20 |
+ |
|
21 |
+ sc := bufio.NewScanner(f) |
|
22 |
+ for sc.Scan() { |
|
23 |
+ line := sc.Text() |
|
24 |
+ fields := strings.Split(line, " ") |
|
25 |
+ if strings.HasPrefix(fields[4], daemon.repository) { |
|
26 |
+ mnt := fields[4] |
|
27 |
+ mountBase := filepath.Base(mnt) |
|
28 |
+ if mountBase == "mqueue" || mountBase == "shm" { |
|
29 |
+ logrus.Debugf("Unmounting %+v", mnt) |
|
30 |
+ if err := mount.Unmount(mnt); err != nil { |
|
31 |
+ return err |
|
32 |
+ } |
|
33 |
+ } |
|
34 |
+ } |
|
35 |
+ } |
|
36 |
+ |
|
37 |
+ if err := sc.Err(); err != nil { |
|
38 |
+ return err |
|
39 |
+ } |
|
40 |
+ |
|
41 |
+ logrus.Debugf("Cleaning up old shm/mqueue mounts: done.") |
|
42 |
+ return nil |
|
43 |
+} |
... | ... |
@@ -62,19 +62,6 @@ func New() *configs.Config { |
62 | 62 |
Data: "newinstance,ptmxmode=0666,mode=0620,gid=5", |
63 | 63 |
}, |
64 | 64 |
{ |
65 |
- Device: "tmpfs", |
|
66 |
- Source: "shm", |
|
67 |
- Destination: "/dev/shm", |
|
68 |
- Data: "mode=1777,size=65536k", |
|
69 |
- Flags: defaultMountFlags, |
|
70 |
- }, |
|
71 |
- { |
|
72 |
- Source: "mqueue", |
|
73 |
- Destination: "/dev/mqueue", |
|
74 |
- Device: "mqueue", |
|
75 |
- Flags: defaultMountFlags, |
|
76 |
- }, |
|
77 |
- { |
|
78 | 65 |
Source: "sysfs", |
79 | 66 |
Destination: "/sys", |
80 | 67 |
Device: "sysfs", |