X Tutup
Skip to content

Commit 3b4fcf7

Browse files
authored
Merge pull request containerd#2112 from crosbymichael/temp-mounts
Add temp mount location to manage temp mounts
2 parents fc87dce + b2ec177 commit 3b4fcf7

File tree

5 files changed

+119
-48
lines changed

5 files changed

+119
-48
lines changed

cmd/containerd/command/main.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"time"
2929

3030
"github.com/containerd/containerd/log"
31+
"github.com/containerd/containerd/mount"
3132
"github.com/containerd/containerd/server"
3233
"github.com/containerd/containerd/sys"
3334
"github.com/containerd/containerd/version"
@@ -111,6 +112,14 @@ func App() *cli.App {
111112
if err := applyFlags(context, config); err != nil {
112113
return err
113114
}
115+
// cleanup temp mounts
116+
if err := mount.SetTempMountLocation(filepath.Join(config.Root, "tmpmounts")); err != nil {
117+
return errors.Wrap(err, "creating temp mount location")
118+
}
119+
// unmount all temp mounts on boot for the server
120+
if err := mount.CleanupTempMounts(0); err != nil {
121+
return errors.Wrap(err, "unmounting temp mounts")
122+
}
114123
address := config.GRPC.Address
115124
if address == "" {
116125
return errors.New("grpc address cannot be empty")

mount/mount.go

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,6 @@
1616

1717
package mount
1818

19-
import (
20-
"context"
21-
"io/ioutil"
22-
"os"
23-
24-
"github.com/containerd/containerd/log"
25-
"github.com/pkg/errors"
26-
)
27-
2819
// Mount is the lingua franca of containerd. A mount represents a
2920
// serialized mount syscall. Components either emit or consume mounts.
3021
type Mount struct {
@@ -47,42 +38,3 @@ func All(mounts []Mount, target string) error {
4738
}
4839
return nil
4940
}
50-
51-
// WithTempMount mounts the provided mounts to a temp dir, and pass the temp dir to f.
52-
// The mounts are valid during the call to the f.
53-
// Finally we will unmount and remove the temp dir regardless of the result of f.
54-
func WithTempMount(ctx context.Context, mounts []Mount, f func(root string) error) (err error) {
55-
root, uerr := ioutil.TempDir("", "containerd-WithTempMount")
56-
if uerr != nil {
57-
return errors.Wrapf(uerr, "failed to create temp dir")
58-
}
59-
// We use Remove here instead of RemoveAll.
60-
// The RemoveAll will delete the temp dir and all children it contains.
61-
// When the Unmount fails, RemoveAll will incorrectly delete data from
62-
// the mounted dir. However, if we use Remove, even though we won't
63-
// successfully delete the temp dir and it may leak, we won't loss data
64-
// from the mounted dir.
65-
// For details, please refer to #1868 #1785.
66-
defer func() {
67-
if uerr = os.Remove(root); uerr != nil {
68-
log.G(ctx).WithError(uerr).WithField("dir", root).Errorf("failed to remove mount temp dir")
69-
}
70-
}()
71-
72-
// We should do defer first, if not we will not do Unmount when only a part of Mounts are failed.
73-
defer func() {
74-
if uerr = UnmountAll(root, 0); uerr != nil {
75-
uerr = errors.Wrapf(uerr, "failed to unmount %s", root)
76-
if err == nil {
77-
err = uerr
78-
} else {
79-
err = errors.Wrap(err, uerr.Error())
80-
}
81-
}
82-
}()
83-
if uerr = All(mounts, root); uerr != nil {
84-
return errors.Wrapf(uerr, "failed to mount %s", root)
85-
}
86-
87-
return errors.Wrapf(f(root), "mount callback failed on %s", root)
88-
}

mount/temp.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package mount
2+
3+
import (
4+
"context"
5+
"io/ioutil"
6+
"os"
7+
8+
"github.com/containerd/containerd/log"
9+
"github.com/pkg/errors"
10+
)
11+
12+
var tempMountLocation = os.TempDir()
13+
14+
// WithTempMount mounts the provided mounts to a temp dir, and pass the temp dir to f.
15+
// The mounts are valid during the call to the f.
16+
// Finally we will unmount and remove the temp dir regardless of the result of f.
17+
func WithTempMount(ctx context.Context, mounts []Mount, f func(root string) error) (err error) {
18+
root, uerr := ioutil.TempDir(tempMountLocation, "containerd-mount")
19+
if uerr != nil {
20+
return errors.Wrapf(uerr, "failed to create temp dir")
21+
}
22+
// We use Remove here instead of RemoveAll.
23+
// The RemoveAll will delete the temp dir and all children it contains.
24+
// When the Unmount fails, RemoveAll will incorrectly delete data from
25+
// the mounted dir. However, if we use Remove, even though we won't
26+
// successfully delete the temp dir and it may leak, we won't loss data
27+
// from the mounted dir.
28+
// For details, please refer to #1868 #1785.
29+
defer func() {
30+
if uerr = os.Remove(root); uerr != nil {
31+
log.G(ctx).WithError(uerr).WithField("dir", root).Errorf("failed to remove mount temp dir")
32+
}
33+
}()
34+
35+
// We should do defer first, if not we will not do Unmount when only a part of Mounts are failed.
36+
defer func() {
37+
if uerr = UnmountAll(root, 0); uerr != nil {
38+
uerr = errors.Wrapf(uerr, "failed to unmount %s", root)
39+
if err == nil {
40+
err = uerr
41+
} else {
42+
err = errors.Wrap(err, uerr.Error())
43+
}
44+
}
45+
}()
46+
if uerr = All(mounts, root); uerr != nil {
47+
return errors.Wrapf(uerr, "failed to mount %s", root)
48+
}
49+
return errors.Wrapf(f(root), "mount callback failed on %s", root)
50+
}

mount/temp_unix.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// +build !windows
2+
3+
package mount
4+
5+
import (
6+
"os"
7+
"path/filepath"
8+
"sort"
9+
"strings"
10+
)
11+
12+
// SetTempMountLocation sets the temporary mount location
13+
func SetTempMountLocation(root string) error {
14+
root, err := filepath.Abs(root)
15+
if err != nil {
16+
return err
17+
}
18+
if err := os.MkdirAll(root, 0700); err != nil {
19+
return err
20+
}
21+
tempMountLocation = root
22+
return nil
23+
}
24+
25+
// CleanupTempMounts all temp mounts and remove the directories
26+
func CleanupTempMounts(flags int) error {
27+
mounts, err := Self()
28+
if err != nil {
29+
return err
30+
}
31+
var toUnmount []string
32+
for _, m := range mounts {
33+
if strings.HasPrefix(m.Mountpoint, tempMountLocation) {
34+
toUnmount = append(toUnmount, m.Mountpoint)
35+
}
36+
}
37+
sort.Sort(sort.Reverse(sort.StringSlice(toUnmount)))
38+
for _, path := range toUnmount {
39+
if err := UnmountAll(path, flags); err != nil {
40+
return err
41+
}
42+
if err := os.Remove(path); err != nil {
43+
return err
44+
}
45+
}
46+
return nil
47+
}

mount/temp_unsupported.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// +build windows
2+
3+
package mount
4+
5+
// SetTempMountLocation sets the temporary mount location
6+
func SetTempMountLocation(root string) error {
7+
return nil
8+
}
9+
10+
// CleanupTempMounts all temp mounts and remove the directories
11+
func CleanupTempMounts(flags int) error {
12+
return nil
13+
}

0 commit comments

Comments
 (0)
X Tutup