github.com/rawahars/moby@v24.0.4+incompatible/daemon/snapshotter/mount.go (about) 1 package snapshotter 2 3 import ( 4 "os" 5 "path/filepath" 6 7 "github.com/containerd/containerd/mount" 8 "github.com/docker/docker/daemon/graphdriver" 9 "github.com/docker/docker/pkg/idtools" 10 "github.com/moby/locker" 11 "github.com/sirupsen/logrus" 12 ) 13 14 const mountsDir = "rootfs" 15 16 // List of known filesystems that can't be re-mounted or have shared layers 17 var refCountedFileSystems = []string{"fuse-overlayfs", "overlayfs", "stargz", "zfs"} 18 19 // Mounter handles mounting/unmounting things coming in from a snapshotter 20 // with optional reference counting if needed by the filesystem 21 type Mounter interface { 22 // Mount mounts the rootfs for a container and returns the mount point 23 Mount(mounts []mount.Mount, containerID string) (string, error) 24 // Unmount unmounts the container rootfs 25 Unmount(target string) error 26 } 27 28 // inSlice tests whether a string is contained in a slice of strings or not. 29 // Comparison is case sensitive 30 func inSlice(slice []string, s string) bool { 31 for _, ss := range slice { 32 if s == ss { 33 return true 34 } 35 } 36 return false 37 } 38 39 // NewMounter creates a new mounter for the provided snapshotter 40 func NewMounter(home string, snapshotter string, idMap idtools.IdentityMapping) Mounter { 41 if inSlice(refCountedFileSystems, snapshotter) { 42 return &refCountMounter{ 43 home: home, 44 snapshotter: snapshotter, 45 rc: graphdriver.NewRefCounter(checker()), 46 locker: locker.New(), 47 idMap: idMap, 48 } 49 } 50 51 return mounter{ 52 home: home, 53 snapshotter: snapshotter, 54 idMap: idMap, 55 } 56 } 57 58 type refCountMounter struct { 59 home string 60 snapshotter string 61 rc *graphdriver.RefCounter 62 locker *locker.Locker 63 idMap idtools.IdentityMapping 64 } 65 66 func (m *refCountMounter) Mount(mounts []mount.Mount, containerID string) (target string, retErr error) { 67 target = filepath.Join(m.home, mountsDir, m.snapshotter, containerID) 68 69 _, err := os.Stat(target) 70 if err != nil && !os.IsNotExist(err) { 71 return "", err 72 } 73 74 if count := m.rc.Increment(target); count > 1 { 75 return target, nil 76 } 77 78 m.locker.Lock(target) 79 defer m.locker.Unlock(target) 80 81 defer func() { 82 if retErr != nil { 83 if c := m.rc.Decrement(target); c <= 0 { 84 if mntErr := unmount(target); mntErr != nil { 85 logrus.Errorf("error unmounting %s: %v", target, mntErr) 86 } 87 if rmErr := os.Remove(target); rmErr != nil && !os.IsNotExist(rmErr) { 88 logrus.Debugf("Failed to remove %s: %v: %v", target, rmErr, err) 89 } 90 } 91 } 92 }() 93 94 root := m.idMap.RootPair() 95 if err := idtools.MkdirAllAndChown(target, 0700, root); err != nil { 96 return "", err 97 } 98 99 return target, mount.All(mounts, target) 100 } 101 102 func (m *refCountMounter) Unmount(target string) error { 103 if count := m.rc.Decrement(target); count > 0 { 104 return nil 105 } 106 107 m.locker.Lock(target) 108 defer m.locker.Unlock(target) 109 110 if err := unmount(target); err != nil { 111 logrus.Debugf("Failed to unmount %s: %v", target, err) 112 } 113 114 if err := os.Remove(target); err != nil { 115 logrus.WithError(err).WithField("dir", target).Error("failed to remove mount temp dir") 116 } 117 118 return nil 119 } 120 121 type mounter struct { 122 home string 123 snapshotter string 124 idMap idtools.IdentityMapping 125 } 126 127 func (m mounter) Mount(mounts []mount.Mount, containerID string) (string, error) { 128 target := filepath.Join(m.home, mountsDir, m.snapshotter, containerID) 129 130 root := m.idMap.RootPair() 131 if err := idtools.MkdirAndChown(target, 0700, root); err != nil { 132 return "", err 133 } 134 135 return target, mount.All(mounts, target) 136 } 137 138 func (m mounter) Unmount(target string) error { 139 return unmount(target) 140 141 }