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